java之file和IO流
目录
File
编辑
IO流
字节流
FileOutputStream:向本地磁盘输出文件
FileInputStream读取本地文件编辑
拷贝文件
字符集
字符流
如何区分什么时候使用字节流,什么时候使字符流呢?
缓冲流
转换流
序列化流
字节打印流
字符转换流
Hutool FileUtil 常用方法讲解
导入依赖
Maven 依赖
常用方法
1. file 方法
2. touch 方法
方法讲解
4. appendLines 方法
5. readLines 方法
6. readUtf8Lines 方法
7. copy 方法
File
package file;
import java.io.File;
public class demo1 {
public static void main(String[] args) {
File file = new File("D:\\javacode\\My_Thread");
System.out.println(file.isFile()); // 是否是一个文件
System.out.println(file.isDirectory()); // 是否是一个文件夹
System.out.println(file.exists()); // 是否存在
// file.length() 返回文件的大小(字节数)
// 这个方法只能获取文件的大小,单位是字节,如果单位我们要是M,6,可以不断的除以1024
// 这个方法无法获取文件夹的大小
File file1 = new File("D:\\DataGrip 2024.1.3\\build.txt");
System.out.println(file1.length());
// file.getAbsoluteFile()获取绝对路径
System.out.println("========================");
System.out.println(file1.getAbsoluteFile());
System.out.println("=========================");
// file.getPath() 返回定义文件时使用的路径 括号内的参数是什么返回的就是什么
System.out.println(file.getPath());
System.out.println("=========================");
// file.getName() 获取名字
// 如果是文件, 会返回文件名+后缀名
// 如果是文件夹 会返回文件夹的名字
System.out.println(file1.getName());
System.out.println(file.getName());
}
}
1. createNewFile 创建一个新的空的文件夹
如果当前路径表示的文件是不存在的,则创建成功,方法返回true,如果当前路径表示的文件是存在的,则创建失败,方法返回false。
如果父级路径是不存在的,那么方法会有异常IOException
createNewFile 方法创建的一定是文件,如果路径中不包含后缀名,则创建一个没有后缀的文件
2. mkdir 创建一个单级文件夹
windows当中路径是唯一的,如果当前路径已经存在,则创建失败,返回false
mkdir方法只能创建单级文件夹,无法创建多级文件夹
3. mkdirs 创建多级文件夹
既可以创建单级的,又可以创建多级的文件夹
4. delete 删除空的文件
如果删除的是文件,则直接删除,不走回收站。如果删除的是空文件夹,则直接删除,不走回收站如果删除的是有内容的文件夹,则删除失败
IO流
字节流
FileOutputStream:向本地磁盘输出文件
package IO;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class demo2 {
public static void main(String[] args) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream("test.txt",true);
// 第二个参数表示续写,也就是不会清空原来文件里面的数据
byte []b = {97,98,99,100};
// fileOutputStream.write(b);
// 参数一: 数组
//参数二: 起始索引
//参数三: 个数
fileOutputStream.write(b,1,2); // 98 99-> b c
String n = "\r\n"; // 换行
byte[] bytes = n.getBytes();
fileOutputStream.write(bytes);
String s = "你真可爱!!!";
byte[] bytes1 = s.getBytes();
fileOutputStream.write(bytes1);
fileOutputStream.close();
}
}
FileInputStream读取本地文件
拷贝文件
package IO;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class demo5 {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("D:\\桌面\\新建文本文档.txt");
FileOutputStream fos = new FileOutputStream("src\\IO\\copy.txt");
byte[] bytes= new byte[2]; // 一般数组长度可以定义为1024*1024*5 -> 5 MB
int len;
while((len = fis.read(bytes)) != -1){
fos.write(bytes,0,len); // 读多少,写多少
}
// 先打卡的后关闭
fos.close();
fis.close();
}
}
字符集
UTF-8不是一种字符集是Unicode的一种编码方式
字符流
如何区分什么时候使用字节流,什么时候使字符流呢?
只需要记住一点,那就是如果是拷贝文件的时候就使用字节流。
如果是读写文件就是字符流
拷贝文件夹的时候存在子文件 ,代码示例:
使用字节流
package IO;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class practice {
public static void main(String[] args) throws IOException {
// 拷贝一个文件夹考虑子文件夹
File src = new File("D:\\桌面\\奖状");
File dest = new File("D:\\奖状copy");
copydir(src,dest);
}
private static void copydir(File src, File dest) throws IOException {
// 创建文件夹
dest.mkdirs();
File[] files = src.listFiles();
for (File file : files) {
if(file.isDirectory()){
// 说明是一个文件夹 递归
// 需要递归调用时在 dest 的基础上拼接当前子文件夹名,生成目标文件夹路径,从而保持源文件夹的层级结构
copydir(file,new File(dest,file.getName()));
}else{
FileInputStream fis = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(new File(dest,file.getName()));
// 这里不能仅仅用dest,因为 dest 是当前级文件夹路径,需要为每个文件或子文件夹指定完整路径。
/*
需要在 dest 的基础上拼接文件名,生成完整的目标文件路径
假设 src 是 D:\桌面\奖状\file1.txt。
//dest 是 D:\奖状copy。
如果直接用 dest,那么程序会尝试将文件直接写入到 D:\奖状copy,但此路径是一个文件夹路径,不是文件路径,会导致错误。
*/
byte[] b = new byte[5*1024*1024];
int len;
while((len = fis.read(b)) != -1){
fos.write(b,0,len);
}
fos.close();
fis.close();
}
}
}
}
无论使用 FileReader
还是 FileInputStream
,读到的都是字节数据,而不是直接的字符内容,如果直接存储这些 int
值,你看到的可能是数字而不是字符本身。因此,强转为 char
是必要的。 如果使用字节流和 byte[]
缓存,可以直接读写文件,不需要字符的强转
缓冲流
package IO.Buffer;
import java.io.*;
public class demo1 {
public static void main(String[] args) throws IOException {
// 创建字节缓冲流拷贝文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src\\IO\\test.txt"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("src\\IO\\Buffer\\copy.txt"));
// 循环拷贝 一次一个字节
int len;
while((len = bis.read()) != -1){
bos.write(len);
}
// 一次多读写几个字节
byte [] b = new byte[1024];
while ((len = bis.read(b)) != -1){
bos.write(b,0,len);
}
// 释放资源
bos.close();
bis.close();
}
}
package IO.Buffer;
import java.io.*;
// 使用缓冲字符流来一行一行拷贝
public class demo2 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("src\\IO\\test.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("src\\IO\\Buffer\\copyChar.txt"));
String read;
while((read = br.readLine()) != null){
bw.write(read);
bw.newLine();
}
bw.close();
br.close();
}
}
注意,在写入本地文件的时候。当本地文件存在该文件 就会清空该文件内容。所以使用IO流我们有一个原则就是随用随New随关。
转换流
1. 指定字符集读写(JDK11之后淘汰了)
2. 字符流想要使用字符流里面的方法
代码示例:
利用转换流按照指定的字符编码读取
package IO.Bridge;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
public class demo1 {
public static void main(String[] args) throws IOException {
// 利用转换流按照指定字符编码读取
// JDK11之前需要创建InputStreamReader和OutPutStreamWriter
// JDK11之后的替代方案:直接创建FileReader对象
FileReader fr = new FileReader("D:\\桌面\\新建文本文档.txt", Charset.forName("GBK"));
FileWriter fw = new FileWriter("src\\IO\\Bridge\\boy.txt",Charset.forName("GBK"));
int len;
while((len = fr.read()) != -1){
fw.write((char) len);
}
fw.close();
fr.close();
}
}
package IO.Bridge;
import java.io.*;
public class demo2 {
public static void main(String[] args) throws IOException {
// 利用字节流读取文件的数据,每次读取一整行,而且不能出现乱码
// 字节流读取数据会出现乱码 所以我们需要利用字符流
// 字节流不能一整行读 所以我们需要结合字符缓冲流
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("src\\IO\\Bridge\\boy.txt")));
String line;
while((line = br.readLine())!= null){
System.out.println(line);
}
}
}
序列化流
序列化流
package IO.Serialization;
import java.io.*;
public class demo1 {
public static void main(String[] args) throws IOException {
Student student = new Student("南京", "张三",24);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src\\IO\\Serialization\\serialization.txt"));
oos.writeObject(student);
oos.close();
}
}
/*
需要实现Serializable这个接口 没有抽象方法,标记型接口
r一旦实现类这个接口,那么就表示当前的Student类可以被序列化
*/
class Student implements Serializable {
@Serial
private static final long serialVersionUID = -518532692387043786L; // 定义一个UID版本号
// transient :瞬态关键字
private transient String addr;
@Override
public String toString() {
return "Student{" +
"addr='" + addr + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
public Student(String addr, String name, int age) {
this.addr = addr;
this.name = name;
this.age = age;
}
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
}
反序列化流
package IO.Serialization;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class demo2 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src\\IO\\Serialization\\serialization.txt"));
Student o = (Student) ois.readObject();
System.out.println(o);
ois.close();
}
}
字节打印流
字符转换流
字符打印流和字节打印流的方法是一样的
Hutool FileUtil
常用方法讲解
FileUtil
是 Hutool 中一个强大的文件操作工具类,提供了文件读写、创建、删除、拷贝等常用操作。
导入依赖
在项目中使用 Hutool 之前,需要添加依赖。
Maven 依赖
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.20</version>
</dependency>
常用方法
1. file
方法
功能: 根据参数创建一个 File
对象。
使用场景: 用于获取一个 File
对象,而不需要关心文件或目录是否存在。
File file = FileUtil.file("example.txt");
System.out.println(file.getAbsolutePath());
2. touch
方法
功能: 根据参数创建一个文件。
特点:
如果文件已存在,则返回已存在的文件。
如果文件不存在,则会创建新的文件。
使用场景: 用于快速创建文件。
File file = FileUtil.touch("newFile.txt");
System.out.println("文件是否存在: " + file.exists());
方法讲解
以下是您提供图片中涉及到的 Hutool FileUtil
方法的详细说明和用法:
功能: 将集合中的数据写入到文件中,采用覆盖模式。
参数说明:
数据集合 (Collection<?>
类型)。
文件路径或 File
对象。
字符集编码。
使用场景: 用于将一组数据快速写入到文件中,覆盖旧内容。
示例代码:
List<String> lines = Arrays.asList("第一行", "第二行", "第三行");
FileUtil.writeLines(lines, "example.txt", Charset.forName("UTF-8"));
4. appendLines
方法
功能: 将集合中的数据追加到文件中,不覆盖原有内容。
参数说明: 与 writeLines
相同。
使用场景: 用于在已有文件内容后追加新数据。
List<String> lines = Arrays.asList("追加内容1", "追加内容2");
FileUtil.appendLines(lines, "example.txt", Charset.forName("UTF-8"));
5. readLines
方法
功能: 按指定字符集编码读取文件内容,并将每一行作为集合的一个元素。
参数说明:
文件路径或 File
对象。
字符集编码。
使用场景: 用于逐行读取文件内容。
示例代码:
List<String> lines = FileUtil.readLines("example.txt", Charset.forName("UTF-8"));
lines.forEach(System.out::println);
6. readUtf8Lines
方法
功能: 按 UTF-8 编码格式读取文件内容,返回集合。
特点: 专门针对 UTF-8 编码文件的快捷读取。
使用场景: 用于读取 UTF-8 格式的文件内容。
List<String> lines = FileUtil.readUtf8Lines("example.txt");
lines.forEach(System.out::println);
7. copy
方法
功能: 拷贝文件或目录。
参数说明:
源文件路径或 File
对象。
目标文件路径或 File
对象。
是否覆盖目标文件(boolean
类型)。
使用场景: 用于文件或目录的复制。
FileUtil.copy("source.txt", "destination.txt", true);
FileUtil.copy("sourceDir", "destinationDir", true);
FileUtil
简化了许多常见的文件操作,推荐在 Java 项目中广泛使用!