File和流一
1、File概述
在java的世界中,万事万物皆对象;在Linux中,万物皆文件。而程序的运行就是在Linux服务器中来进行运行的。
对于文件来说,java利用File来进行封装,File代表的是对文件和文件夹的抽象表示。
也就是说用一个File来表示文件和文件夹,在当前的操作系统中对于一个File来说,代表的可能不是一个真实的文件,仅仅只是一个路径名,在而磁盘上,可能是存在的,也可能是不存在的。所以file也就面临着为空的情况。
下面附上一个总结图:
对于文件来说,文件的内容不能够使用File来进行读取,而是通过流的方式来进行读取。File对象可以用来表示流的来源地和目的地。
File类中只是提供了一些创建、查找、删除文件,但是却无法对文件的内容来进行操作。所以只能够通过流的操作方式来进行操作。
所以使用流主要是用来实现对内容的读取、传输和写入数据的。又称为IO操作
3、IO分类
1. 字节流
1. 概述
IO : I : IN;O : OUT
计算机中存储数据:最小的存储单元是字节
输入和输出 : 站在内存的角度思考
- IO流的分类
输入 | 输出 | |
---|---|---|
字节 | 字节输入流(InputStream) | 字节输出流 |
字符 | 字符输入流 | 字符输出流 |
2. 字节输入流
- FileInputStream : 从文件中读取字节
(1 ) 构造方法
// 创建字节输入流对象, 关联到文件(路径)上
public FileInputStream(File file)
public FileInputStream(String name)
注意 : 关联的文件如果不存在会报错, 如果关联的是文件夹也会报错
(2) 成员方法
public int read() : 读取一个字节, 返回: 读取到的字节
如果读取到文件末尾, 会返回-1
public int read(byte[] b)
: 读取字节数组, 将读取到的字节存入数组中,
返回: 读取到有效的字节个数
如果读到文件的末尾, 会返回-1
// 了解即可
public int read(byte[] b, // 字节数组
int offset, // 起始偏移量(索引)
int len) // 长度
: 读取字节数组, 将字节读取到数组中, 从offset开始的 len 个
public void close() : 关流
3. 字节输出流
- FileOutputStream : 输出字节到文件上
(1)构造方法
// 创建字节输出流对象, 关联文件
public FileOutputStream(File file)
public FileOutputStream(String name)
// 以上两种构造方法, 创建输出流对象, 关联文件中的内容会被清空.
// 输出流关联的文件如果不存在, 会创建出来
(2) 成员方法
public void write(int b) : 写出一个字节
public void write(byte[] b) : 写出字节数组(将字节数组中的内容写到文件上)
public void write(byte[] b, // 字节数组
int off, // 索引
int len) // 长度
: 写出字节数组中, 从off索引开始的 len 个字节
4. 一个字节的拷贝
package com.guang._06copy;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
字节流一个字节一个字节的拷贝
*/
public class Demo01 {
public static void main(String[] args) throws IOException {
// 1. 创建输入流对象
FileInputStream fis = new FileInputStream("day12-code\\def.mp4");
// 2. 创建输出流对象
FileOutputStream fos = new FileOutputStream("day12-code\\copyDef.mp4");
// 3. 使用输入流读取
int b; // 代表每一次读取到的字节
while ((b = fis.read()) != -1) {
// 4. 使用输出流写出
fos.write(b);
}
// 5. 关闭输出流
fos.close();
// 6. 关闭输入流
fis.close();
}
}
5. 字节数组的拷贝
package com.guang._06copy;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
read(byte[] arr) : 将文件中的字节, 读取到字节数组中,
返回的是读取到有效的字节个数
读取到文件末尾, 返回-1
write(byte[] arr, int offset, int len) :
将arr数组中 从offset索引开始的 len个字节, 写出到文件中
*/
public class Demo02 {
public static void main(String[] args) throws IOException {
// 1. 创建输入流对象
FileInputStream fis = new FileInputStream("day12-code\\def.mp4");
// 2. 创建输出流对象
FileOutputStream fos = new FileOutputStream("day12-code\\copyDef.mp4");
// 3. 使用输入流读取
// 创建字节数组
byte[] arr = new byte[1024 * 8];
// 创建变量, 用来记录读取到有效的字节个数
int len;
while ((len = fis.read(arr)) != -1) {
// 4. 使用输出流写出
fos.write(arr, 0, len);
}
// 5. 关闭输出流
fos.close();
// 6. 关闭输入流
fis.close();
}
}
四. 字符流
1. 概述
当使用字节流读取文本文件时,可能会有一个小问题。就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储。所以Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文件。
2. 字符输入流
- FileReader
(1) 构造方法
FileReader(String pathname)
FileReader(File file)
(2) 成员方法
public int read()
public int read(char[] cbuf)
public abstract int read(char[] cbuf,
int off,
int len)
3. 字符输出流
- FileWriter
(1) 构造方法
public FileWriter(File file)
public FileWriter(String fileName)
(2) 成员方法
public void write(int c) : 写出一个字符
public void write(char[] cbuf) : 写出字符数组
public void write(char[] cbuf, : 写出字符数组中从off索引开始的len个字符
int off,
int len)
public void write(String str) : 可以直接写出字符串
字符流的使用场景:
- 仅读取中文字符
- 仅写出中文字符
所有格式文件的拷贝, 都使用字节流.
4. 字符流拷贝
字符流只能拷贝纯文本的文件(我们能看得懂的)
5. 其他知识点
(1) 关闭和刷新
FileOutputStream : 内部没有任何缓冲区(数组)
FileWriter : 内部有一个长度为1024的字符数组 --- 缓冲区
写出的内容会先被写到缓冲区中, 然后再刷出到文件上
缓冲区中的内容, 刷出到文件上有两种情况:
- 缓冲区满了, 会自动刷 2. 手动刷(close, flush)
- close() : 关流, 但是在关流之前, 会刷出一次缓冲区.
- flush() : 刷出一次缓冲区.
flush本意是冲刷,这个方法大概取自它引申义冲马桶的意思,马桶有个池子,你往里面扔东西,会暂时保存在池子里,只有你放水冲下去,东西才会进入下水道。
同理很多流都有一个这样的池子,专业术语叫缓冲区,当你print或者write的时候,会暂时保存在缓冲区,并没有发送出去,这是出于效率考虑的,因为数据不会自己发送过去,必须有其他机制,而且这个很消耗资源,就像马桶你需要很多水,才能冲走,你如果扔一点东西,就冲一次水,那你水费要爆表了,同样如果你写一行文字,或者一个字节,就要马上发送出去,那网络流量,CPU使用率等等都要爆表了,所以一般只有在你真正需要发送否则无法继续的时候,调用flush,将数据发送出去。
什么时候使用呢?其实看接口,都可以来进行使用。所以推荐使用完成之后flush一下即可。
(2) 换行和续写
-
换行符
- "\r\n" 换行符
- "\t" 制表符
-
续写
public FileOutputStream(String name, boolean append) : append: 是否续写 public FileWriter(String fileName, boolean append)