1.按照流向分类:
1.输入流:从物理内存中读取数据到运行内存(读)
2.输出流:从内存写出数据到硬盘(写)
一个文件在传输过程中经历了多次的拷贝粘贴,IO的性能本身很低的
零拷贝,Nio附加题!!
2.按照操作单元分:
1.字节流:一个字节一个字节的操作,二进制操作,可以操作任意类型的文件 2.字符流:是一个字符一个字符的操作。一个字符两个字节,主要用来操作文本文 件 txt .java .py .xml
3.按照角色划分
1.结点流:操作一个特定的IO设备
2.处理流:在结点流的基础上做进一步的处理。
在Java中输入输出流中常用的流:
字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 | |
---|---|---|---|---|
抽象基类 | InputStream | OutputStream | Reader | Writer |
访问文件 | FileInputStream | FileOutputStream | FileReader | FileWriter |
缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter |
操作对象 | ObjectInputStream | ObjectOutputStream |
流到底怎么用?
输入流:就是一点一点的往内存中读数据!
字节输入流:
1.创建一个FileInputStream对象
2.定义一个标记,用来控制输入流的读取
3.循环读取,如果读取到了-1,说明读取到了文件的末尾,循环结束
4.关闭资源。********
注意:我们发现一个流读完了就没有了,不能再读了。
当一个流读完之后会默认调用mark和reset方法来进行记录和重置,这个流就已经重置到了上次读完的位置,所以就无法再次读取内容。并不是读完一次之后就关闭了流。
字节输出流
FileOutputStream构造器:
boolean append参数:如果传入true,则代表在原有基础上追加,不覆盖如果传入false,或者不传,覆盖原有内容
写的操作,目标文件如果不存在,会自动新建。
两个流:
FileInputStream:把对应文件的内容读取出来
FileOutputStream:把读到的内容写出去
read(byte[])
write(byte[])
多个流同时使用时:
流的关闭顺序的问题?先用的流后关,后用的先关!!!
在jdk1.7之后,很多资源类实现了AutoCloseable接口
包括我们常见的流,FileInputStream,FileOutputStream…
可以在try中定义资源,并会主动释放资源
了解即可!!
字符处理流(用的最多)
缓冲流
只能处理纯文本文件:.txt,.java,.html,.css…
利用缓冲字符流来写一个文件的复制
@Test public void test02() { BufferedWriter bufferedWriter = null; try { bufferedWriter = new BufferedWriter(new FileWriter("e:/xxx.txt")); bufferedWriter.write("今天是星期二,天气凉爽!"); System.out.println("数据写出成功!"); } catch (IOException e) { throw new RuntimeException(e); } finally { bufferedWriter.close(); } }
序列化与反序列化:操作对象
序列化:将对象写入到IO流中,将内存模型的对象变成字节数字,
可以进行存储和传输。
反序列化:从IO流中恢复对象,将存储在硬盘上或者从网络中接收的数据
恢复成对象模型
使用场景:所有可在网络上传输的对象都必须是可序列化的,
否则会报错,所有保存在硬盘上的对象也必须要可序列化。
序列化版本号:
反序列化必须拥有class文件,但随着项目的升级,class文件也会升级
序列化保证升级前后的兼容性。
java序列化提供了一个版本号
版本号是可以自由指定,如果不指定,JVM会根据类信息自己计算一个版本号,
所以无法匹配,则报错!!!
不指定版本号,还有一个隐患,不利于JVM的移植,可能class文件没有改,
但是不同的jvm计算规则不一样,导致无法反序列化
如果只修改了方法,反序列化是不受影响,无需修改版本号修改了静态变量static,瞬态变量transient,反序列化也不受影响,无需修改版本号
总结:
-
所有需要网络传输的对象都需要实现序列化接口
-
对象的类名、实例变量都会被序列化;方法、类变量、transient变量不会被序列化
-
如果想让某个变量不被序列化,可以用transient修饰
-
序列化对象的引用类型成员变量,也必须是可序列化的,否则会报错
-
反序列化时必须有序列化对象的class文件
-
同一个对象被序列化多次,只有第一次序列化为二进制流,以后都只是保存序列化的版本号
-
建议所有可序列化的类加上版本号,方便项目升级。