流的概念
流是数据流动,有输入流输出流,程序和io设备或文件之间进行传输的对象,功能是完成数据的输入输出。
这一章其实还是学一个类库。
I/O流的分类
Java流支持两种数据:
1.原始字节
2.Unicode字符
则可按照读写数据类型分类
1.字节流(流)
2.字符流(阅读器、书写器)
图中是四个抽象类。
InputStream
OutputStream
flush是清空缓存,把缓存写入文件中去
Reader
Writer
节点流和处理流
节点流
如果用字节流读含有中文的文件,那么中文会变成?
,因为它是一个字节一个字节读出来的,而中文一个字两个字节。改用字符流就可以解决,因为字符流在读出字节后会自动转化为字节。
举例:
如果没有要写入的文件,就会新建,如果有,就会覆盖,如果不想覆盖,可以写FileOutStream("文件名",true)
过滤流
工作原理
缓冲流
套接在节点流或其他处理流之上,提高读写效率,给数据的读写提供了缓冲功能
注意:缓存输出流的作用是将输出数据先缓存起来,等待缓存区满了之后一次性输出来提高通道利用率,在调用缓存输出流的close方法的时候,会调用被装饰对象的write方法,如果被装饰对象被提前关闭了,那么自然就抛出异常
import java.io.*;
public class TestFileStreamToCopyPdf {
public static void main(String[] args)
{
int b = 0;
FileInputStream in = null;
FileOutputStream out = null;
BufferedInputStream bufR = null;
BufferedOutputStream bufW = null;
try {
in = new FileInputStream("1.pdf");
out = new FileOutputStream("22.pdf");
bufR = new BufferedInputStream(in);
bufW = new BufferedOutputStream(out);
while((b = bufR.read()) != -1) {
bufW.write(b);
}
//这里如果最后关闭bufW会出错
bufW.close();
in.close();
bufR.close();
out.close();
}catch(FileNotFoundException e2){
System.out.println("找不到指定文件");
System.exit(-1);
}catch(IOException e1) {
System.out.println("文件复制错误");
System.exit(-1);
}
System.out.println("文件已复制");
}
}
如果没有涉及到缓存输出流,而是使用其他过滤流,那么就无所谓关闭顺序了
参考博客
上面这个例子还有个问题,如果不使用包装流则复制不成功,我猜可能是文件太大了。
转换流
可以把字节流转换成字符流
数据流
直接以基本类型为单元进行读写,提供了可以存取Java基本数据类型数据的方法
Print流
只有输出流:PrintStream PrintWriter
System.out就是用PrintStream,out就是PrintStream类型的静态成员。
对象流
对象序列化
使用对象流实现序列化:
总结
课上课后问题
1.FileReader()一般用平台默认的编码模式(如GBK),而用InputStreamReader 可以根据不同编码标准读可以以指定的编码格式来读,例如:BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), "UTF-8"));
这样可以读GBK读出UTF-8。这也是转换流的意义所在。
2.InputStreamReader isr = new InputStreamReader(new FileInputStream("..."));
这样读非纯文本文档也是不可以的,只要底层不是txt,就不能读字符或用转换流读字符。