IO流是用来处理设备之间的数据传输,Java对数据的操作是通过流的方式进行,而操作流的对象都封装到java.io包中。根据操作数据的种类可以把IO流分为字节流(InputStream,OutputStream)和字符流(Reader,Writer)或者根据流的流向分为输入流(InputStream,Reader)输出流(OutputStream,Writer)
字符流中继承体系结构:
字节流中的继承体系结构:
FileWriter:字符输出流专门写入文本数据,使用后需要调用flush()方法,在close()方法后会自动内部刷新缓冲中的数据,因为是调用操作系统底层的资源进行文件操作,所以必须手动关闭资源,这个不是虚拟机垃圾回收机制能够回收的。
FileReader:字符输入流可以使用char[]缓冲读取字符中的数据。使用try{}catch{}finally{}进行异常处理和资源回收。
BufferedWriter:字符输出流缓冲区是为了提高流的操作效率而出现的,所以在创建缓冲区之前,必须要先有流对象。该缓冲区中提供了一个跨平台的换行符newLine()。
BufferedReader:字符输入流缓冲区,该缓冲区提供了一个一次读一行的方法 readLine(),方便于对文本数据的获取,readLine方法返回的时候只返回回车符之前的数据内容,并不返回回车符。
FileInputStream:字节输入流,原始的字节操作除了可以操作文本数据还可以操作视频、音频、图片等其他字符流不能操作的类型数据
System.out:对应的是标准输出设备(PrintStream),控制台。System.in:对应的标准输入设备(InputStream):键盘输入。
InputStreamReader:字节输入流转换器,可以把字节输入流转换成字符输入流。
OutputStreamWriter:字节输出流转换器,可以把字节输出流转换成字符输出流。
流操作的基本规律:
最痛苦的就是流对象有很多,不知道该用哪一个。
通过三个明确来完成。
1,明确源和目的。
源:输入流。InputStream Reader
目的:输出流。OutputStream Writer。
2,操作的数据是否是纯文本。
是:字符流。
不是:字节流。
3,当体系明确后,在明确要使用哪个具体的对象。
通过设备来进行区分:
源设备:内存,硬盘。键盘
目的设备:内存,硬盘,控制台。
File:文件对象,不仅可以操作文件还可以操作对应的文件夹
Properties:属性对象,是hashtable的子类也就是说它具备map集合的特点。而且它里面存储的键值对都是字符串,是集合中和IO技术相结合的集合容器。该对象的特点:可以用于键值对形式的配置文件。那么在加载数据时,需要数据有固定格式:键=值。
SequenceInputStream:合并多个流,对应的使用的就是Vector添加多个流对象。
PipedInputStream,PipedOutputStream管道流可以直接读取和写入数据
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream();
in.connect(out);
RandomAccessFile该类不是算是IO体系中子类。而是直接继承自Object。但是它是IO包中成员。因为它具备读和写功能。内部封装了一个数组,而且通过指针对数组的元素进行操作。可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置。其实完成读写的原理就是内部封装了字节输入流和输出流。通过构造函数可以看出,该类只能操作文件。而且操作文件还有模式:只读r,,读写rw等。
DataInputStream与DataOutputStream可以用于操作基本数据类型的数据的流对象。
ByteArrayInputStream :在构造的时候,需要接收数据源,。而且数据源是一个字节数组。
ByteArrayOutputStream: 在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组。(因为这两个流对象都操作的数组,并没有使用系统资源。所以,不用进行close关闭。)
编码:字符串->字节数组,解码:字节数组->字符串。出现乱码就是编码使用的格式生成的数字用另一种编码格式进行解码导致码表中无法读取正确的字符,当显示?表示没有找到对应的字符(我们会使用的基本也就是GBK和UTF-8,乱码也就是没有控制两者的统一),