Java文件操作

刚学完文件操作

今天刚学了文件操作,比 Python 困难了许多,因为用到的方法和类比较多,比较杂
但方法多了,可以做的事情就更多了,能进行的操作也就更多、更灵活了

File 类

File 类就是用来创建一个文件对象,它的构造方法里面传入的不管这个文件夹或者文件是否存在,都可以被创建,没问题
File 类有三个构造方法

1
2
3
4
5
File f1 = new File("/home/nero"); //创建File对象,只是把字符串路径封装为File对象,不考虑路径的真假情况

File f2 = new File("/home", "demo.txt"); //一个父路径,一个子路径,把路径分成了两个部分

File f3 = new File(f1, "java.txt"); //父路径是File类的对象,子路径是字符串

常用的一些方法

1
2
3
4
5
6
7
8
9
10
11
12
String absolute = f.getAbsolutePath(); //不管传入的是相对路径还是决定路径,都返回绝对路径

String path = f.getPath(); //获取路径名称字符串

String name = f.getName(); //获取文件名称字符串

f.exists(); //判断文件是否存在

f.isFile(); //判断路径是否以文件结尾

f.isDirectory(); //判断路径是否以文件夹结尾
//文件不存在时,isFile和isDirectory都返回false

创建与删除

可以通过 File 实例化的对象来创建文件或者文件夹

  • 创建文件
1
2
File f = new File("demo.txt");
boolean b = f.createNewFile();
  • 创建文件夹
1
2
3
4
File f1 = new File("Dir");
boolean b1 = f1.mkdir(); //创建单级文件夹
File f2 = new File("Dir1/Dir2/Dir3");
boolean b2 = f2.mkdirs(); //创建多级文件夹
  • 删除文件或文件夹
1
2
3
4
5
6
 File f1 = new File("Dir");
boolean b1 = f1.delete(); //既能删除文件,也能删除文件夹
File f2 = new File("demo.txt");
boolean b2 = f2.delete();
File f3 = new File("Dir1/Dir2/Dir3"); //删除多级文件夹要写全
boolean b3 = f3.delete();

字节流

以字节的方式读取/写入文件,就是把01代码一连串的处理一遍
此处的 input 和 output 是相对于内存的
input 就是从硬盘读取数据到内存
output 就是从内存写入数据到硬盘

FileInputStream 类

创建一个以字节流的方式读取的文件对象

1
2
3
4
5
6
7
8
FileInputStream fis = new FileInputStream("Test.txt"); //创建一个读取文件的对象
System.out.println(fis.read()); //读取一个字节

int len = 0;
while ((len = fis.read()) != -1){ //循环遍历所有字节
System.out.println((char) len);
}
fis.close();

read() 方法会反回一个字节,如果读取到了文件末尾,则反回 -1

利用 byte 数组来加快读取速度

1
2
3
4
5
6
7
FileInputStream fis = new FileInputStream("Test.txt");
byte[] br = new byte[1024]; //用来存储读取出来的字节
int len = fis.read(br); //len表示有效读取字节个数
while ((len = fis.read(bytes)) != -1){ //循环遍历所有字节
System.out.println(new String(bytes, 0, len)); //输出有效的字节数,这样输出的时候后面就不会有多余的空格了
}
br.close();

FileOutputStream 类

创建一个以字节流的方式写入的文件对象

1
2
3
FileOutputStream fos = new FileOutputStream("Test.txt"); //构造方法传入写入数据的目的地
fos.write(97); //写入字节,一次只能传入一个字节
fox.close();

以上方式一次只能传入一个字节,很麻烦,可以传入一个字节数组

1
2
3
4
5
6
FileOutputStream fos = new FileOutputStream("justTest.txt");
byte[] arr = {97, 48, 49, 68, 72, 100};
fos.write(arr); //写入一串字节

byte[] arr2 = "你好世界".getBytes(); //getBytes()方法反回一个字节数组
fos.write(arr2);

FileOutputStream 类可以传入第二个参数true/false,表示是否追加写

字符流

字节流是一次处理一个字节,字符流就是一次处理一个字符,由于中文占两到三个字节,所以用字节流处理中文会乱码

FileReader 类

以字符流读取字符
用法和字节流差不多,只不过反回的是字符

1
2
3
4
5
6
FileReader fr = new FileReader("Test.txt");
int len = 0;
while ((len = fr.read()) != -1){ //和字节流的 read() 方法一样,一次读取一个字符,读取完毕返回 -1
System.out.println((char)len);
}
fr.close();

一次读取多个字符

1
2
3
4
5
6
7
FileReader fr = new FileReader("Test.txt");
char[] ch = new char[1024];
int len = 0;
while ((len = fr.read(ch)) != -1){
System.out.println(new String(ch, 0, len)); //输出有效的字符数,这样输出的时候后面就不会有多余的空格了
}
fr.close();

FileWriter 类

以字符流写入字符

1
2
3
4
FileWriter fw = new FileWriter("Test.txt", true); //true 表示使用追加写
fw.write("HelloWorld");
fw.flush(); //写入数据到硬盘中
fw.close();

Properties 集合

Properties 集合是一种特殊的集合,它可以把数据以键值对的方式存储,并且可以写入到特定的文件,方便以后读取使用

存储

1
2
3
4
5
6
7
8
Properties prop = new Properties(); //创建Properties 集合对象
prop.setProperty("ShaMiKo", "150");
prop.setProperty("MoMo", "140");
try (FileWriter fw = new FileWriter("prop.txt")){ //处理异常,使用 try...catch 可以自动关闭流
prop.store(fw, "save data"); //store() 方法写入到fw创建的对象对应的文件中,第二个参数是注释
} catch (IOException e){
e.printStackTrace();
}

读取

Properties 集合的load方法可以读取文件(键值对)到集合中
void Load (InputStream inputStream) 字节输入,不能读中文
void Load (Reader reader) 字符输入,可以读中文

1
2
3
4
5
6
7
8
9
10
try (FileReader fr = new FileReader("prop.txt");){
prop.load(fr);
Set<String> arr = prop.stringPropertyNames();
for (String s : arr) {
String value = prop.getProperty(s);
System.out.println(s + "=" + value);
}
} catch (IOException e){
e.printStackTrace();
}

缓冲区

创建一个缓冲区,这样可以提高文件的读取/存储效率
有四个缓冲区类

  • BufferedOutputStream() –> 字节缓冲输出流
  • BufferedInputStream() –> 字节缓冲输入流
  • BufferedWriter() –> 字符缓冲输出流
  • BufferedReader() –> 字符缓冲输入流

用法都差不多
BufferedOutputStream() 方法

1
2
3
4
FileOutputStream fos = new FileOutputStream("test.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos, 1024); //第二个参数设置缓冲区大小,不写就用默认的大小
bos.flush(); //写入硬盘
bos.close();

FileInputStream() 方法

1
2
3
FileInputStream fis = new FileInputStream("test.txt");
BufferedInputStream bis = new BufferedInputStream(fis, 1024); //第二个参数设置缓冲区大小,不写就用默认的大小
fis.close();

BufferedWriter() 方法

1
2
3
4
FileWriter fw = new FileWriter("test.txt");
BufferedWriter bw = new BufferedWriter(fw, 1024); //第二个参数设置缓冲区大小,不写就用默认的大小
bw.flush(); //写入硬盘
bw.close();

BufferedReader() 方法

1
2
3
FileReader fr = new FileReader("test.txt");
BufferedReader br = new BufferedReader(fr, 1024); //第二个参数设置缓冲区大小,不写就用默认的大小
br.close();

输出流

输出流可以很方便的把各种数据输入到文件中

  • PrintStream: 输出的是字节
  • PrintWriter: 输出的是字符
  • 两者用法几乎一样
1
2
3
4
5
6
7
PrintStream ps = new PrintStream("print.txt"); //创建打印流,绑定目标文件
ps.write(97); //使用继承自父类的write方法,那么写入的时候会查询编码表
ps.println(97); //使用自己特有的print/println方法,会原样输出
ps.println("阿巴阿巴");
ps.println('c');
ps.println(3.14);
ps.close();

print.txt 文件内容如下

1
2
3
4
a97
阿巴阿巴
c
3.14

输出流就是把输出到命令行的数据,输出到文件中
可以用 System 下的 setOut() 方法把输出到命令行的文字重定向到文件

1
2
3
4
5
System.out.println("控制台输出");
PrintStream ps = new PrintStream("目的地是打印流.txt");
System.setOut(ps);
System.out.println("我在打印流中输出");
ps.close();

有一段时间没有学习 Java 了,跑去学别的东西了,现在又有时间回来继续学习 Java 了 ♪(^∀^●)ノシ
文件操作应该蛮重要的,但看上去并不是很难理解,可能是以前学过类似的东西吧 (●´∀`●)