节点流
FileReader和FileWriter
字符流(cha[]数组)
FileReader读入数据的基本操作
过程
1、 实例化File类的对象,指明要操作的文件
注意:
* 在@Test测试中的相对路径是相对于当前Module
* 在main函数的相对路径是相对于当前工程
2、 提供具体的流
3、 数据的读入过程
4、 流的关闭操作
5、 try-catch-finally异常处理
说明
- 一定要注意最后流的关闭
- read()的理解:返回读入的一个字符。如果达到文件末尾,返回-1
- 异常的处理:为了保证流资源一定可以执行关闭的操作,需要使用try-catch-finally来处理
- 读入的文件(hello.txt)一定要存在,否则会报FileNotFoundException异常
代码实现
@org.junit.Test
public void test1(){
FileReader fileReader = null;
try {
//1. 实例化File类的对象,指明要操作的文件
//注意:在@Test测试中的相对路径是相对于当前Module,在main函数的相对路径是相对于当前工程
File file = new File("hello.txt");//相对路径
//2. 提供具体的流
fileReader = new FileReader(file);
//3. 数据的读入过程
//read():返回读入的一个字符。如果达到文件末尾,返回-1
//方式一
// int data = fileReader.read();
// while(data != -1){
// System.out.print((char)data);
// data = fileReader.read();
// }
//方式二:语法上针对方式一的修改
int data;
while((data = fileReader.read()) != -1){
System.out.println((char)data);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//4. 流的关闭操作
try {
//防止最开始提供流是出现异常导致这里是空指针,所以加一个判断
if(fileReader != null){
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果
此时的”hello.txt”文档中存储的内容是hello
使用read()的重载方法
- read():返回读入的一个字符。如果达到文件末尾,返回-1
- read(char[] cbuf):返回每次读入cbuf数组中的字符的个数。如果达到文件末尾,返回-1(常用)
- read(char cbuf[], int off, int len) (不常用)
read(char[] cbuf)的用法
1、 创建一个char的数组cbuf
(举例假定该数组的长度为5)
> char\[\] cbuf = new char\[5\];
2、 创建len变量,存储read(char[] cbuf)的返回值
(注意:返回值即为每次读入cbuf数组中的字符的个数)
3、 读取数据
* 写法一:循环遍历
for (int i = 0; i < len; i++) {
System.out.print(cbuf[i]);
}
* 写法二:char\[\]类型和String类型转换
String str = new String(cbuf,0,len);
System.out.print(str);
[https://tech.souyunku.com/CrabDumplings/p/13341279.html][https_tech.souyunku.com_CrabDumplings_p_13341279.html]
![70\_2.png][70_2.png]
4、 流的关闭操作(不要忘记)
read(char[] cbuf)读取数据时的注意事项
- 写法一
for (int i = 0; i < len; i++) {
System.out.print(cbuf[i]);
}
其中for循环时,i一定要小于len(每次读入cbuf数组中的字符的个数)而不是cbuf.length
* 画图说明:
![70\_3.png][70_3.png]
最后还剩下3个数据的时候:
* 如果for循环中的i小于cbuf.length(错误的写法)
![70\_4.png][70_4.png]
最后的输出为:helloWorld123ld
(其中hello为第一次的结果,World为第二次的结果,123ld为第三次的结果)
而文件中的内容为helloWorld123,所以此时的写法是错误的
* 如果for循环中的i小于len(正确的写法)
![70\_5.png][70_5.png]
最后的输出为:helloWorld123
(其中hello为第一次的结果,World为第二次的结果,123为第三次的结果)
* 写法二
String str = new String(cbuf,0,len);
System.out.print(str);
其中利用了String(char\[\] value, int offset, int count)构造器,而不是String(char\[\] value)构造器
* String(char\[\] value)构造器(错误的写法)
错误原因与写法一错误的方法相同
* String(char\[\] value, int offset, int count)构造器(正确的写法)
读取char\[\]数组中角标0到角标len的内容,过程与写法一正确的方法过程类似
FileReader写出数据的基本操作
过程
1、 实例化File类的对象,指明要操作的文件
2、 提供具体的流
3、 数据的写出过程
4、 流的关闭操作
5、 try-catch-finally异常处理
说明
写出操作,对应的File可以不存在。
- 如果不存在,在写出的过程中,会自动创建此文件
- 如果存在这个文件
- 对原有文件的覆盖
流使用的构造器为
FileWriter(file, false)
或者是
FileWriter(file)
- 在原有文件的基础上追加内容(不会对原有文件进行覆盖)
流使用的构造器为
FileWriter(file, true)
- 对原有文件的覆盖
代码实现
FileWriter fw1 = null;
FileWriter fw2 = null;
try {
//1. 提供File类的对象,指明写出到的文件
File file = new File("hi.txt");
//2. 提供FileWriter的对象,用于文件的写出
//覆盖
fw1 = new FileWriter(file,false);
//不覆盖
fw2 = new FileWriter(file,true);
//3. 写出的操作
fw1.write("I have a dream!\n");
fw2.write("123\n");
} catch (IOException e) {
e.printStackTrace();
}finally {
//4. 关闭流资源
if(fw1 != null)
try {
fw1.close();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fw2 != null)
try {
fw2.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果
最开始hi.txt文件中的内容为hello
运行代码后
使用FileWriter和FileReader实现文本文件的复制
过程
1、 创建File类的对象,指明读入和写出的文件
2、 创建输入流和输出流的对象
3、 数据的读入和写入操作
4、 关闭流资源
5、 try-catch-finally异常处理
说明
- 在读取文件文件时,选择read(char[] cbuf)的用法
- 在写入文件的时候,注意不要写成
fw.write(cbuf);
此时出现的错误和读取操作时写法一会出现的错误相同,不可以正确的读取文件中原本的内容
需要使用
fw.write(cbuf,0,len);
读取cbuf数组中角标为0的元素到角标为len的元素
-
在最后关闭流资源的时候,一定要注意两个流都要关闭,即使其中一个流在关闭的时候抛出异常另一个流也要关闭
有两种写法
- 写法一
finally {
//4. 关闭流资源
if(fr != null)
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(fw != null)
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
* 写法二
finally {
//4. 关闭流资源
try {
if(fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fw != null)
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
代码实现
public void test4(){
FileReader fr = null;
FileWriter fw = null;
try {
//1. 创建File类的对象,指明读入和写出的文件
File file1 = new File("hello.txt");
File file2 = new File("hi.txt");
//2. 创建输入流和输出流的对象
fr = new FileReader(file1);
fw = new FileWriter(file2,true);
//3. 数据的读入和写入操作
char[] cbuf = new char[5];
int len;//记录每次读入到cbuf数组中字符的个数
while((len = fr.read(cbuf)) != -1){
//每次写出len个字符
fw.write(cbuf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//4. 关闭流资源
try {
if(fr != null)
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fw != null)
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果
注意
字符流不能处理图片文件等字节数据!!!
FileInputStream和FileOutputStream
字节流(byte[])
使用FileInputStream和FileOutputStream实现文本文件的复制
过程
1、 创建File类的对象,指明读入和写出的文件
2、 创建输入流和输出流的对象
3、 数据的读入和写入操作
4、 关闭流资源
5、 try-catch-finally异常处理
代码实现
FileInputStream fis = null;
FileOutputStream fos = null;
try {
File srcfile = new File("殷志源.png");
File destfile = new File("丸子.png");
fis = new FileInputStream(srcfile);
fos = new FileOutputStream(destfile);
byte[] buffer = new byte[5];
int len;
while((len = fis.read(buffer)) != -1){
fos.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fis != null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
运行结果
指定路径下文件的复制的方法
复制视频
public void copyFile(String srcPath, String destPath){
FileInputStream fis = null;
FileOutputStream fos = null;
try {
File srcfile = new File(srcPath);
File destfile = new File(destPath);
fis = new FileInputStream(srcfile);
fos = new FileOutputStream(destfile);
byte[] buffer = new byte[1024];
int len;
while((len = fis.read(buffer)) != -1){
fos.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fis != null)
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fos != null)
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字节流和字符流使用的注意事项
- 对于文本文件(.txt, .java, .c, .cpp……),使用字符流来处理
- 对于非文本文件(.jpg, .mp3, .mp4, .avi, .doc, .ppt……),使用字节流来处理
- 如果只是想复制文本文件,也可以使用字节流(流在此时只是个搬运的作用)
- 非文本只可以用字节流操作