超详细JAVA-IO流知识点
1.1 IO流:
- I(Input): 将硬盘中的数据,读取到内存中。
- O(Output): 将内存中的数据,写入到硬盘中。
- 流: 数据(字节,字符)1个字符 = 2个字节 ;1 个字节 = 8 个二进制
1.2 分类:
输入流 | 输出流 | |
---|---|---|
字节流 | 字节输入流(InputStream) | 字节输出流(Outputstream) |
字符流 | 字符输入流(Reader) | 字符输出流(Writer) |
2 字节流
2.1 java.io.OutputStream:字节输出流**
此抽象类是表示输出字节流的所有类的超类。将字节写入到文件中
2.1.1. 子类:java.io.FileOutputStream:文件字节输出流
- 作用:把内存中的数据写入到硬盘的文件中。
- 构造方法:
FileOutputStream(File file)
:创建一个向指定 File 对象表示的文件中写入数据的文件输出流。FileOutputStream(String name)
:创建一个向具有指定名称的文件中写入数据的输出文件流。FileOutputStream(File file, boolean append)
:创建一个向指定 File 对象表示的文件中写入数据的文件输出流。FileOutputStream(String name, boolean append)
:创建一个向具有指定 name 的文件中写入数据的输出文件流。- 参数:写入数据的目的地。
- File file:目的地是一个文件。
- String name:目的地是一个文件的路径。
- boolean append:追加写开关。
- true:创建对象不会覆盖文件,继续在文件末尾追加写数据。
- false:创建一个新文件覆盖旧文件。
- 作用:
- 创建一个FileOutputStream对象。
- 会根据构造方法中传递的文件/文件路径,创建一个空文件。
- 会把FileOutputStream对象指向创建好的文件。
2.1.2. 写入数据的原理(内存->硬盘):
2.1.3. 使用步骤(重点):
- 创建一个FileOutputStream对象,构造方法中传递写入数据的目的地。
- 调用FileOutputStream对象中的方法write,把数据写入到文件中。
- 释放资源(流使用会占用一定的内存资源,使用完毕要把内存情况,提高程序的效率)
2.1.4. 常用方法:
-
void write(byte[] b)
:将 b.length 个字节从指定 byte 数组写入此文件输出流中。- 参数:
- 如果第一个字节为(0-127)则查询ASCⅡ码表。
- 如果第一个字节为负数,那么第一个字节将和第二个字节组成中文显示。
- 参数:
-
void write(byte[] b, int off, int len)
:将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。-
参数:
- byte[] b:将该数组中的数据写入到文件中。
- int off:需要写入数据的起始位置。
- int len : 需要写入数据的长度。
-
案例:
// 创建FileOutputStream对象,并给定目的文件路径,和是否续写。 FileOutputStream fos = new FileOutputStream("\\a.txt",true); // 给定需要写入的数据数组 byte[] bytes = "你好!中国!".getBytes(); // 利用for循环进行写入 for (int i = 0; i < 10; i++) { // 由于编译器为utf-8编码,所以一个中文字符为3个字节。将中国!写入 fos.write(bytes,9,9); // 插入换行符 fos.write("\n".getBytes()); } // 释放资源 fos.close();
-
-
void write(int b)
:将指定字节写入此文件输出流。
- 注意:
- 该类声明了一个 FileNotFoundException 异常。所以一定要处理。
- 在存储十进制数时,计算机会自动转化为2进制数存储,而记事本等文本编辑器会将其转化为字符显示。
- 0-127 ,查询ASCⅡ表。
- 其他值:查询系统默认的码表。
- 写字符的方法:
- 先使用String类中的getBytes()方法、将字符转换为字节数组。
- 在使用FileOutputStream类中的write()方法进行写入。
- 换行符号:
- Windows:\r\n
- Linux:/n
- Mac:/r
2.2 java.io.InputStream:字节输入流
此抽象类表示所有字节输入流的所有类的超类,可以读取字节信息到内存中
2.2.1.子类:java.io.FileInputStream:文件字节输入流
- 作用:将硬盘文件中的数据读取到内存中。
- 构造方法:
FileInputStream(File file)
: 通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的 File 对象 file 指定。FFileInputStream(String name)
:通过打开一个到实际文件的连接来创建一个 FileInputStream,该文件通过文件系统中的路径名 name 指定。- 参数:读取文件的数据源。
- File file:数据源是一个文件。
- String name:数据源是一个文件的路径。
- boolean append:追加写开关。
- true:创建对象不会覆盖文件,继续在文件末尾追加写数据。
- false:创建一个新文件覆盖旧文件。
- 作用:
- 创建一个FileInputStream对象。
- 会把FileOutputStream对象指向构造方法中要读取的文件。
2.2.2. 读取数据的原理(硬盘->内存):
2.2.3. 使用步骤(重点):
- 创建一个FileInputStream对象,构造方法中绑定要读取的数据源。
- 调用FileInputStream对象中的方法read,读取文件。
- 释放资源(流使用会占用一定的内存资源,使用完毕要把内存情况,提高程序的效率)
-
常用方法:
-
int read()
:从此输入流中读取一个数据字节。-
返回值:下一个数据字节;如果已到达文件末尾,则返回 -1。
-
案例:
FileInputStream fileInputStream = new FileInputStream("\\a.txt"); int len = 0; while((len = fileInputStream.read()) != -1){ // 条件也可为 >0 // 利用强制类型转换,直接输出字符 System.out.println((char)len); } fileInputStream.close();
-
-
int read(byte[] b)
:从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。 【创建缓冲区进行读取】-
返回值:读入到有效字节的个数。
-
参数:byte[] b 存储读取数据的缓冲区。
-
案例:
// 创建一个FileInputStream对象,构造方法中绑定要读取的数据源。 FileInputStream fileInputStream = new FileInputStream("\\a.txt"); // 创建数据缓冲区。 byte[] bytes = new byte[1024]; // 接收读取到的有效字节的个数 int len = 0; // 循环遍历 while((len = fileInputStream.read(bytes)) != -1){ // 利用String构造方法,截取数据缓冲区的有效字节。 System.out.println(new String(bytes,0,len)); } // 释放资源 fileInputStream.close();
-
-
2.3. 案例: 复制文件
// 给定需要复制源文件的地址路径
FileInputStream fileInputStream = new FileInputStream("F:\\1.jpg");
// 给定需要复制目的文件的地址路径
FileOutputStream fileOutputStream = new FileOutputStream("E:\\1.jpg", true);
// 利用数据缓冲区的方式读取,可以提高程序效率
byte[] bytes = new byte[1024];
int len = 0;
while((len = fileInputStream.read(bytes)) != -1){
// 将读取到的文件写入目的文件
fileOutputStream.write(bytes,0,len);
}
// 关闭写入文件资源
fileOutputStream.close();
// 关闭读出文件资源
fileInputStream.close();
3. 字符流
由于字节流每次只读取一个字节,而中文是由2-3个字节组成,所以我们需要学习字符流读取。
3.1 java.io.reader:字符输入流
该抽象类是字符输入流的最顶层的父类,用于将文件中的字符读入到内存中
-
子类: java.io.FileReader(文件字符输入流) extends java.io.InputStreamReader
-
作用: 将文件中的数据以字符的方式读取到内存中。
-
构造方法:
FileReader(File file)
:在给定从中读取数据的 File 的情况下创建一个新 FileReader。FileReader(String fileName)
:在给定从中读取数据的文件名的情况下创建一个新 FileReader。- 参数:
- File file:读取的目的文件。
- String fileName: 读取的目的文件的路径。
- FileReader构造方法的作用:
- 创建一个FileReader对象。
- 将FileReader对象指向要读取的文件。
-
使用步骤:
- 创建FileReader对象,并在构造方法中绑定需要读取的文件路径
- 使用FileReader类中的read()方法读取文件
- 释放资源。
-
常用方法:
-
int read()
:读取单个字符。- 案例:
// 创建FileReader对象 FileReader fileReader = new FileReader("\\1.jpg"); int len = 0; // 循环遍历 while((len = fileReader.read()) != -1){ System.out.println((char)len); } // 释放资源 fileReader.close();
-
int read(char[] cbuf)
:(该方法为Reader类的方法)将字符读入数组中的某一部分。- 案例:
FileReader fileReader = new FileReader("\\a.txt"); char[] chars = new char[1024]; int len = 0; while((len = fileReader.read()) != -1){ System.out.println(new String(chars, 0, len)); } fileReader.close();
-
-
3.2 java.io.Writer:字符输出流
该抽象类是所有字符输出流的最顶层的父类,用于将内存中的数据写入到硬盘文件中
-
子类:java.io.FileWriter(文件字符输出流) extends java.io.OutputStreamWriter
-
作用: 将内存中的数据以字符的方式写入到文件中。
-
构造方法:
FileWriter(File file)
:根据给定的 File 对象构造一个 FileWriter 对象。FileWriter(String fileName)
:根据给定的文件名构造一个 FileWriter 对象。FileWriter(String fileName, boolean append)
FileWriter(File file, boolean append)
- 参数:
- File file:写入的目的文件。
- String fileName: 写入的目的文件的路径。
- 构造方法的作用:
- 创建FileWriter对象。
- 会根据构造方法中传递的文件/文件路径创建文件。
- FileWriter对象指向创建好的文件。
-
使用步骤(重点)
- 创建一个FileWriter对象、构造方法中绑定需要写入数据的文件或文件路径
- 利用FileWriter中的wirte()方法将数据写入到内存缓冲区之中、并不是直接写入到文件中(由于文件都是以字节存储的,所以必须将字符转换为字节进行写入)
- 利用FilerWriter中的flush()方法,把内存缓冲区的数据,刷新到文件中。(可省略)
- 释放资源、利用FilerWriter中的close()方法。(会自动把内存缓冲区的数据刷新到文件中)
-
常用方法:
-
void write(int c)
:写入单个字符。- 案例:
// 创建一个FileWriter对象 FileWriter filterWriter = new FileWriter("\\a.txt"); // 将数据写入到内存缓冲区之中 filterWriter.write(97); // 把内存缓冲区的数据,刷新到文件中。 filterWriter.flush(); // 释放资源 filterWriter.close();
-
int read(char[] cbuf, int offset, int length)
:将字符读入数组中的某一部分。 -
int read(String , int offset, int length)
:将字符读入数组中的某一部分。- 案例:
FileWriter fileWriter = new FileWriter("\\a.txt"); // 写入字符数组 fileWriter.write(new char[]{'I',' '}); fileWriter.flush(); // 写入字符串 fileWriter.write("Love You"); // 写入整型数据 fileWriter.write((byte)' '); // 写入指定位置的字符串 fileWriter.write("China Number One", 0, 5); fileWriter.close();
-
-
flush()方法和close()方法的区别:
- flush()方法:刷新缓冲区,流对象可以继续使用。
- close()方法:刷新缓冲区,然后通知系统释放资源,流对象无法使用。
-
注意:
- 续写:
- 原理与OutputStream相同,利用构造方法进行绑定。
- 换行:
- Windows:\r\n
- Linux:/n
- Mac:/r
- 续写:
-
4. 流中异常处理:
4.1 处理方法try…catch:
案例:
// 提升FileWriter对象的作用域,否则finally代码块无法调用此对象
// 且局部变量必须赋初值。
FileWriter fileWriter = null;
// 存放会出现问题的代码
try{
// 创建FileWriter对象,并绑定路径
fileWriter = new FileWriter("\\a.txt");
// 写入数据
fileWriter.write(97);
// 刷新数据
fileWriter.flush();
}catch(IOException e){
// 打印异常信息
System.out.println(e);
} finally {
// 由于fileWriter对象初值为NUll,防止try中赋值失败,所以进行判空!
if(fileWriter != null){
// close方法本身就声明了异常、所以也的进行捕获并处理
try{
// 释放资源(由于改代码必须实现所以放再finally中)
fileWriter.close();
}catch (IOException e){
System.out.println(e);
}
}
}
4.2 JDK 7新特性:
- 在try后边增加了一个(),括号中可以定义流对象(且可以定义多个流对象)、此对象的作用域在try中有效。
- try在执行完代码之后,自动释放流对象,不用手动写finally和close方法
案例:
try (
// 给定需要复制源文件的地址路径
FileInputStream fileInputStream = new FileInputStre("F:\\1.jpg");
// 给定需要复制目的文件的地址路径
FileOutputStream fileOutputStream = new FileOutputStre("E:\\1.jpg",true);
) {
// 利用数据缓冲区的方式读取,可以提高程序效率
byte[] bytes = new byte[1024];
int len = 0;
while ((len = fileInputStream.read(bytes)) != -1) {
// 将读取到的文件写入目的文件
fileOutputStream.write(bytes, 0, len);
}
}catch(IOException e){
System.out.println(e);
}
4.3 JDK 9 新特性
- 将jdk7()里面定义的流对象,在try上面定义,而()号里便直接写对象名就好(以分号分隔),但是流对象在外边定义也得throws声明异常。
- 由于博主JDK为1.8 暂不做演示。