关于IO流
关于IO流
1.基本概念
I表示input输入流 ,O表示output输出流, IO流主要用于处理数据传输如读写文件,网络通讯等。
IO流中操作流对象都是成对出现的,一个输入流,一个输出流,所谓输入输出是针对内存来说的。
IO流是一个管道,通过这个管道将外部文件(磁盘,光盘等存储设备的程序)中的数据读入到程序(内存)中称输入流,或将程序中的数据写出到外部文件中称为输出流。
2.分类
- 按操作数据单位不同分为:字节流(8bit),字符流(按字符)
- 按数据流的流向不同分为:输入流,输出流
- 按流的角色不同分为:节点流,处理流/包装流
(抽象基类) | 字节流 | 字符流 |
---|---|---|
输入流 | InputeStream | Reader |
输出流 | OutputStream | Writer |
-
java中的IO流涉及40多种实际上都是从上述四个基类派生的。
-
由这四个基类派生出来的子类名称都是以其父类名作为子类名后缀
IO流图:
3.常用流介绍
3.1. 字节流
字节流是一个节点流,该流与文件关联(直接操作文件),字节流是以字节的形式读写磁盘中的文件,字节流可以操作任何文件但更适合操作非文本文件
InputStram(字节输入流) OutputStream(字节输出流),这两个类是抽象类,常用它的子类FileInputStream(文件字节输入流),FileOuputStream(文件字节输出流)去操作文件。
//创建文件字节输入流对象
InputStream input=new FileInputStream("path");
//input.read();//一次读取一个字节,没有读到返回-1
byte[] buf=new byte[1024];//相当于一个缓冲区,可以一次性读取多个字节数。
int len=-1;
//一次性读取buf数组长度的字节,返回读取字节数的长度,没有读到返回-1
while((len=input.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
input.close();//关闭流
//创建文件字节输出流,第一个参数为路径,第二个参数为是否向文本追加内容,默认为false
OutputStream output=new FileOutputStream("path",true);
byte[] buf=new byte[1024];//相当于一个缓冲区,可以一次性读取多个字节数。
String str="ssssss";
output.write(str.getBytes());//write:将指定的byte数组写入指定的目标文件
output.close();//关闭流
3.2. 转换流
InputStreamReader:将字节输入流转换为字符输入流
OutputStreamWriter:将字节输出流转换为字符输出流
上述两个流可自定义编码集
//创建转换输入流对象,第一个参数:要转换的文件输入字节流,第二个参数:文件编码集,将utf-8的编码转为unicode
Reader reader=new InputStreamReader(new FileInputStream("path"),"utf-8");
int len=-1;
char[] ch=new char[1024];
while((len=reader.read(ch))!=-1){
System.out.println(new String(ch,0,len));
}
reader.close();
//创建一个输出流对象,将unicode编码转换为GBK编码输入到文件中去
Writer writer=new OutputStreamWriter(new FileOutputStream("path"),"GBK");
String str="asdf";
writer.write(str);
writer.close();
3.3.字符流
字符流是以字符为单位读取数据,适合于读写文本文件
最好不要使用字符流去操作二进制文件,例如声音,视频等
FileReader和FileWriter实现字符读写操作的两个简洁的转换流,他们的编码必须为平台编码
3.4.缓冲流
缓冲流是对基础流的一个包装流(处理流),主要用于提高IO流的读写效率; Java中针对字节流和字符流都提供了缓冲流
BufferedInputStream(带有缓冲区的字节输入流)
BufferedOutputStream(带有缓冲区的字节输出流)
BufferedReader(带有缓冲区的字符输入流)
BufferedWriter(带有缓冲区的字符输出流)
注意:字符缓冲流的最大特点是它里面提供了一次读取一行的方法
缓冲流也属于处理流的一种,在关闭处理流时,只需要关闭外层流即可,外层流的底层会自动关闭内层流。
3.6.打印字符输出流
PrintWriter:该流也是带有缓冲区的
该流提供两个比较方便的方法:print(),println()
注意:打印流打印出数据后必须调用printWriter.close();方法,此方法是真正将数据写入文件的操作,相当于flush()+关闭流
3.7.数据流
主要用于读写基本类型的数据:DataInputStream、DataOutputStream这两个用于对文件中的基本类型数据进行读写操作.
数据流根据要读取的数据的类型不同而一次性从文件中读写相对应的字节的数据,来提高对基本类型的读写效率
3.5.对象流
对象流是用于将Java对象写出到硬盘或读入到程序
Java中的对象流使用ObjectInputStream和ObjectOutputStream来实现
ObjectInputStream和ObjectOutputStream都是基于字节流实现的
3.6.序列化与反序列化
基本介绍
- 通过对象流对java的操作就是序列化和反序列化
- java中对象本身是无法在网络中传输或存储到磁盘或其他存储介质的,因为在传输时需要将对象转换为字节流,而这种对象到字节流的转化,我们称之为序列化,接收方或程序读取磁盘上的文件时,将字节流转化为对象称之为反序列化
- java基本类型可以直接在磁盘上进行存储或进行网络传输,不需要序列化或反序列化
- 所有对象类型都需要序列化或反序列化后才能在磁盘上存储或在网络中传输
序列化标识
- 序列化接口:Serializable
- java中可以向磁盘中存入的对象都必须实现序列化
- 序列化接口只是一个标识接口,其中没有任何内容
- 当一个java对象进行序列化或反序列化时,jvm会检测该对象是否实现了序列化接口
序列时的注意事项
- 读写顺序要一致
- 要求序列化或反序列化的对象必须实现serializable接口
- 序列化的类中建议添加serialversionUID(序列化版本号):提高版本兼容性
若对对象序列化后对其类进行代码更改操作,若此类有序列化版本号就不会认为它是一个新的类,只是原先类的升级版 - 序列对象时,默认序列化类中的所有属性,除过static,transient修饰的属性(它们不会被序列化)
- 序列化对象时,要求里面的属性的类型也必须实现序列化接口
- 序列化具有可继承性,若一个类实现的序列化,则它的子类也默认实现了序列化
3.8.标准输入输出流
类型 | 默认设备 | |
---|---|---|
System.in(标准输入流) | 编译期:InputStream 运行期:BufferedInputeStream | 键盘 |
System.out(标准输出) | PrintStream | 显示器 |