- 文件流
- 流的分类
- InputStream
- FileInputStream
- FileReader
- OutputStream
- FileOutputStream
- FileWriter
- 节点流和处理流
- 节点流
- 处理流
- 两者关系
- 对象流
文件在程序中是以流的形式来操作的
- 流:数据在数据源(文件)和程序(内存)之间经历的路径
- 输入流:数据从数据源到程序的路径
- 输出流:数据从程序到数据源的路径
按操作数据单位分为:
- 字符流
- 字节流
按流向不同分为:
- 输入流
- 输出流
按流的角色分为:
- 节点流
- 处理流
它们有:
| 字节流 | 字符流 | |
|---|---|---|
| 输入流 | InputStream | Reader |
| 输出流 | OutputStream | Writer |
其中,上述类都是抽象类
- Java 的 IO 流涉及 40 多个类,实际上非常规则,都是从如上 4 个基类派生的
- 它们的派生类都以它们的名字作为后缀
public void fun1() {
String filePath = "C:\Users\acer\Desktop\fileTest.txt";
int readData = 0;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(filePath);
while ((readData = fileInputStream.read()) != -1) {
System.out.print((char)readData);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void fun2() {
String filePath = "C:\Users\acer\Desktop\fileTest.txt";
int readLen = 0;
// 字节数组
byte[] buf = new byte[8];
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(filePath);
// 从输入流读取 buf 数组长度的内容到数组中
// 如果读取正常,返回实际读到的字符数,否则返回 -1
while ((readLen = fileInputStream.read(buf)) != -1) {
System.out.print(new String(buf, 0, readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileReader
public static void main(String[] args) {
String filePath = "C:\Users\acer\Desktop\fileTest666.txt";
FileReader fileReader = null;
int data = ' ';
try {
fileReader = new FileReader(filePath);
while ((data = fileReader.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void readFile() {
String filePath = "C:\Users\acer\Desktop\fileTest666.txt";
FileReader fileReader = null;
int readLen = 0;
char[] buf = new char[8];
try {
fileReader = new FileReader(filePath);
while ((readLen = fileReader.read(buf)) != -1) {
System.out.print(new String(buf, 0, readLen));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
OutputStream
FileOutputStream
public void writeFile01() {
String filePath = "C:\Users\acer\Desktop\fileTest.txt";
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(filePath);
fileOutputStream.write('6');
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void writeFile02() {
String filePath = "C:\Users\acer\Desktop\fileTest.txt";
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(filePath);
String str = "YASUO^&^&^*&^^&*&*^*&^n893374987324n328974";
// 写入字符串,需要转换成 byte 数组
fileOutputStream.write(str.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void writeFile03() {
String filePath = "C:\Users\acer\Desktop\fileTest.txt";
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(filePath);
String str = "YASUO^&^&^*&^^&*&*^*&^n893374987324n328974";
// 写入范围内的字符
fileOutputStream.write(str.getBytes(), 0, str.length() - 8);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void writeFile04() {
String filePath = "C:\Users\acer\Desktop\fileTest.txt";
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(filePath, true); // true 表示追加
String str = "YASUO^&^&^*&^^&*&*^*&^n893374987324n328974";
// 写入范围内的字符
fileOutputStream.write(str.getBytes(), 0, str.length() - 8);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileWriter
FileWriter 使用后必须要关闭或者刷新才能真正写入到文件中
public void writeFile01() {
String filePath = "C:\Users\acer\Desktop\fileTest666.txt";
FileWriter fileWriter = null;
char[] chars = {'a', 'b'};
try {
fileWriter = new FileWriter(filePath);
fileWriter.write('T');
fileWriter.write(chars);
fileWriter.write("杰瑞狗4132421".toCharArray(), 0, 3);
fileWriter.write("string21321");
fileWriter.write("STRING", 0, 2);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
// 必须关闭,才能真正写入到文件
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
节点流和处理流
节点流可以从一个特定的数据源读写数据,如 FileReader、FileWriter
处理流处理流,也叫处理流。是“连接”在已存在的流(节点流或者处理流)之上,为程序提供更为强大的读写功能,也更加灵活,如 BufferedReaderBufferedWriter
比如,在 BufferedReader 类中,有一个 Reader 属性,即可以封装一个节点流;BufferedWriter 同理,BufferedWriter 最好不要处理二进制文件,如mp3、视频之类,可能出错
如果使用了处理流的包装类包装节点流,关闭的时候只需要关闭最外层的处理流
两者关系- 节点流是底层流 / 低级流,直接给数据源相连
- 处理流(包装流)包装节点流,既可以消除不同节点流之间的实现差异,也可以提供更方便的方法完成输入输出
- 处理流对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连
处理流的功能主要体现在:
- 性能提高:以增加缓冲的方式提高输入输出的效率
- 操作便捷:可能会提供一系列便捷方法
当需要对 基本数据类型 或者 对象 进行序列化或者反序列化时,会需要用到对象流 ObjectInputStream、ObjectOutputStream
简单地说,序列化就是保存数据的时候同时保存数据类型和值,反序列化就是恢复数据的时候恢复数据类型和值



