Java IO操作
IO流介绍
I:input 输入(读取)
O:output 输出 (写出)
场景:
- 读写配置文件、日志文件
- 客户端和服务端的通讯
- 文件上传和下载
IO流体系结构
| 分类 | 抽象类 | 子类 |
|---|---|---|
| 字节流 | InputStream | FileInputStream |
| OutputStream | FileOutStream | |
| 字符流 | Reader | FileReader |
| Writer | FileWriter |
关流
流对象使用完毕后,记得调用close方法关闭。不及时关闭流对象,则会占用资源,且无法对文件进行删除、修改等操作
当流对象被关闭后,无法再调用读取或写入的方法,除非重新创建流对象
IO流异常处理方式
JDK7之前
1 | try { |
想要解决这个问题,就需要用到finally关键字:
1 | FileOutputStream fos1 = null; // 先提升作用域,否则finally代码块中的fos1无法正确识别 |
JDK7之后
格式:
1 | try (需要调用close方法的流对象) { |
小括号里的流对象,会自动调用close方法,就算有异常也会调用close
示例:
1 | try (FileOutputStream fos = new FileOutputStream("Day04/A.txt")) { |
小括号里的对象,它的类必须要实现了AutoCloseable这个接口,才能正常使用,并且还会自动调用close()这个重写后的方法
FileOutStream
| 构造方法 | 说明 |
|---|---|
| FileOutputStream(String name) | 输出流关联文件,文件路径以字符串形式给出 |
| FileOutputStream(String name, boolean append) | 第二个参数表示追加模式 |
| FileOutputStream(File file) | 输出流关联文件,文件路径以File对象形式给出 |
| FileOutputStream(File file, boolean append) | 第二个参数表示追加模式 |
当关联的文件不存在时,会自动创建
不开启追加模式,关联文件如果存在,会清空现有的,再开始写入
| 成员方法 | 说明 |
|---|---|
| public void write(int i) | 写出一个字节 |
| public void write(byte[] b) | 写出一个字节数组 |
| public void write(byte[] b, int off, int len) | 写出字节数的一部分 |
示例:
1 | // 创建字节输出流对象关联对象 |
想要写出字符串时,可以调用字符串中的getBytes()方法,该方法会返回由字节组成的数组
FileInputStream
| 构造方法 | 说明 |
|---|---|
| FileInputStream(String name) | 输入流关联文件,文件路径以字符串形式给出 |
| FileInputStream(File file) | 输入流关联文件,文件路径以File对象形式给出 |
关联文件如果不存在,会抛出FileNotFoundException异常
文件夹的话会拒绝访问
| 成员方法 | 说明 |
|---|---|
| int read() | 读取一个字节并返回,如果达到文件结尾则返回-1 |
| int read(byte[] b) | 将读取到的字节,放到传入的数组 返回读取到的有效字节个数 如果达到文件结尾则返回-1 字节数组的长度尽量为1024的倍数 |
读取的文件中不能有中文,否则会出乱码中文
read()示例:
1 | // int read() |
read(byte[] b)示例:
1 |
|

可以利用String的构造方法public String(byte[] bytes,int offset,int length)优化以上代码:
1 | try (FileInputStream fis = new FileInputStream("Day04/B.txt")) { |
注意,字节数组的长度尽量设置为1024的倍数,保证性能的同时也可以降低额外的内存占用
文件拷贝案例
假设E:\src目录下有一个img_001.png的文件,需要将其拷贝到E:\dest目录下
- 创建输入流对象读取文件
- 创建输出流对象关联数据目的
- 读写操作
- 关流释放资源
代码:
1 | String srcFilePath = "E:\\src\\img_001.png"; |
FileReader
- 用于读取纯文本文件,解决中文乱码问题
| 构造方法 | 说明 |
|---|---|
| FileReader(String fileName) | 字符输入流关联文件,路径以字符串形式给出 |
| FileReader(File file) | 字符输入流关联文件,路径以File对象形式给出 |
| 成员方法 | 说明 |
|---|---|
| public int read() | 读取单个字符 |
| public int read(char[] cbuf) | 读取一个字符数组,返回读取到的有效字符个数 |
当使用FileInputStream读取中文文本时:
1 | // E:\FileReaderTest\A.txt,文本内容为:你好呀! |
使用FileReader读取中文文本时:
1 | try (FileReader fr = new FileReader("E:\\FileReaderTest\\A.txt")) { |
或:
1 | try (FileReader fr = new FileReader("E:\\FileReaderTest\\A.txt")) { |
FileWriter
| 构造方法 | 说明 |
|---|---|
| FileWriter(String fileName) | 字符输出流关联文件,路径以字符串形式给出 |
| FileWriter(String fileName, boolean append) | 参数2:追加写入模式开关 |
| FileWriter(File file) | 字符输出流关联文件,路径以File对象形式给出 |
| FileWriter(File file) | 参数2:追加写入模式开关 |
| 成员方法 | 说明 |
|---|---|
| public void write(int c) | 写出单个字符 |
| public void write(char[] cbuf) | 写出一个字符数组 |
| public void write(char[] cbuf, int offset, int len) | 写出字符数组的一部分 |
| public void write(String str) | 写出字符串 |
| public void write(String str, int offset, int len) | 写出字符串的一部分 |
示例:
1 | try (FileWriter fw = new FileWriter("Day04/中文文本.txt",true)) { |
注意事项:字符输出流写出数据时,需要调用flush或close方法,数据才会写出
flush():刷出数据,刷出后可以继续写出
close():关闭流释放资源,同时刷出数据,关闭后不可以继续写出
这是因为底层将写出的字符存放在缓冲区中,只有调用对应方法才能将缓冲池的数据彻底写出(缓冲区大小为
1024字符数组长度)
Properties介绍
- Properties类表示一组持久的属性。Properties可以保存到流中或从流中加载。属性列表中的每个键及其对应的值都是一个字符串
- 本质就是Map集合
- 内部存在着两个方法,可以很方便的将集合的键值写入文件,也可以方便的从文件中读取
- 将来加载配置文件的时候很方便
| 方法名 | 说明 |
|---|---|
| Object setProperty(String key, String value) | 类似Map集合的put方法 |
| String getProperty(String key) | 类似Map集合的get方法 |
| Set<String> stringPropertyNames() | 类似Map集合的keySet方法 |
示例:
1 | Properties properties = new Properties(); |
Properties和IO相关的方法
| 方法 | 说明 |
|---|---|
| void load(InputStream inStream) | 从输入字节流读取属性列表(键和元素对) |
| void load(Reader reader) | 从输入字符流读取属性列表(键和元素对) |
| void store(OutputStream out, String comments) | 将此属性列表(键和元素对)写入此Properties表中,以适合于使用load(InputStream)方法的格式写入输出字节流 |
| void store(Writer writer, String comments) | 将此属性列表(键和元素对)写入此Properties表中,以适合使用load(Reader)方法的格式输出字符流 |
加载配置文件:
1 | Properties prop = new Properties(); |
输出配置文件:
1 | Properties prop = new Properties(); |
HuTool
- HuTool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率
- 官网地址:Hutool
| IOUtil类提供的部分方法 | 说明 |
|---|---|
| copy(InputStream in, OutputStream out, int bufferSize) | 字节流拷贝 |
| copy(Reader reader, Writer writer) | 字符流拷贝 |
| readLines(Reader reader, Collection<String> collection) | 按行读取内容到集合 |
| close(Closeable closeables) | 安全关闭流 |
| FileUtil类提供的部分方法 | 说明 |
|---|---|
| touch(filePath) | 创建文件(自动创建父目录) |
| mkdir(dirPath) | 创建目录(支持多级目录) |
| copy(srcPath, destPath, isOverride) | 复制文件或目录(可选覆盖) |
| move(srcFile, destDir, isOverride) | 移动文件或目录 |
引入Jar包:在项目下创建一个文件夹,把要用到的jar包放进去,对这个文件夹右键,点击Add as Library...
IOUtil示例:
1 | // 文件拷贝 |
FileUtil:
1 | FileUtil.touch("E:\\FileUtil\\testA.txt"); |
⚠️危险代码:⚠️
1 | FileUtil.move(new File("E:\\FileUtil\\AAA"),new File("E:\\FileUtil\\AAA\\BBB"),true); // 循环创建嵌套空文件夹 |