个人的理解和总结:
首先要明确 输入输出 是对谁而言的?这里是相对程序而言的,什么是程序,就是你在编写的东西。
所以输入,就是程序从外部读取数据,用InputStream、Reader 里的read、readLin等方法进行读。
输出,就是程序向外部写出数据,用OutputStream、Writer 里的writer、print等方法进行写。
我们平常说的“往一个文件里写入数据”,这句话其实已经改变了相对的对象,听起来像是写入使用输入,其实是错误的理解,这里的写入是相对文件而言,所以改变了相对程序而言这个立场。这里用程序的代码来讲恰恰叫做输出,程序往文件写数据。
关于输入输出流的分类有大体有三种分发,按输入输出分,按是否和特定地方相连,按处理数据的单位分。
1.按输入输出 开头就说了,要知道输入输出的相对立场。
2.按是否和特定地方相连,则分为节点流和处理流。节点流是最基本的流,处理流都是高级流。
自己学的节点流不多,主要就是和文件相关的FileOutputStream、FileInputStream。
3.我从 按处理数据的单位分 这个点进行详细讲解。
两个最基本字节流的抽象父类InputStream、OutputStream
所有继承自这两个父类的都是处理字节的流,因为这两个都是抽象类,所以我们一般用他的继承类。
这里最基本的处理字节的节点流分别是FileInputStream、FileOutputStream
FileInputStream:
构造:FileInputStream(File file)、FileInputStream(StringfileName)
主要方法:int read(int d)、int read(byte[] buf) 这里和raf很类似,不再赘述。
FileOutputStream:
构造:FileOutputStream(File file)、FileOutputStream(StringfileName)
这里有个追加的构造:FileOutputStream(File file,boolean append) 如果append为true则在写入的时候会进行追加,即在原有的内容后追加写入的内容,为false则清空覆盖。
注意:区别于raf的写,包括之后的流的写,只要写入不管写入多长会直接将原有的文件内容清空覆盖,不会像raf写入长度不够进行保留覆盖。
主要方法:void writer(int d) 低8位有效 、void writer(byte[] buf) 写入一个字节数组。
处理字节的高级流:高级流需要一个节点流作为参数
缓冲流:BufferedOutputStream、BufferedInputStream 缓冲流的作用就是先将要读要写的内容放在一个缓冲区,待缓冲区满了进行数据的读写,这样增加内存效率。当然,使用flush和close方法后就会清空缓冲区将区内的内容读写。
BufferedInputStream 缓冲输入流
构造:BufferedInputStream(fis) 方法同FileInputStream
BufferedOutputStream 缓冲输出流
构造:BufferedOutputStream(fos) 方法同FileOutputStream
所以可以这么说 缓冲流的作用就是套在两个节点流外面的,给他们进行加持作用的。
对象流:ObjectOutputStream、ObjectInputStream 专门用来对对象进行存储读取的流,前提对象需要进行一次序列化,说白了就是实现一个接口Serializable,另外最好声明一个静态最终长整型的成员变量作为版本号(具体干嘛看文档,忘记了,反正这样做没错)。
同样因为这时一个高级流,也需要用fis和fos作为其参数。
常用的两个方法,输出对象:oos.writerObject(Object o)
输入对象(读对象):Object o = ois.readObject();
两个最基本的字符流抽象父类:Reader、Writer
因为是字符流,故名思议,主要是对文本文件进行读写操作比较合理,同时涉及到了字符,自然而言就会牵扯到编码集。这两个是抽象父类,所以我们也是使用实现类。
这里学了基本的两个转换流,我个人觉得,从字节处理到字符处理,应该是一个机制的转换,我且认为这两个流算是高级流,因为它们的参数也需要用到fis和fos字节处理流做一个文件的关联。
两个转换流:InputStreaReader、OutputStreamWriter两个转换流的作用是相当于对字节流的一个关联和升级,因为他们的构造没有直接用file的参数。
InputStreaReader:
构造:InputStreaReader(fis,String charsetName) 其中charsetName就是编码集如:”GBK”、”UTF-8”等
当然也可以不设置编码集,则系统默认,看IDE的默认编码设置。
主要方法:int read() 返回的int是低16位有效、int read(char[] chs) 读取字符数组和字节流类似,只是这里是字符数组,返回的int为实际读到的字符个数。
OutputStreamWriter:
构造:OutputStreamWriter(fos, String charsetName)其中charsetName就是编码即输出字符的编码形式,所以当输入读取数据时,必须和该文件写入的编码一致,尤其中文。
主要方法:void writer(int c) 写出int的低16位、voidwriter(char[] chs)、void writer(String)、voidwriter(char[] chs,int offset, int len)
接下来介绍两个高级点的字符处理流:
PrintWriter : 具有自动刷新功能的缓冲字符输出流
构造:这个流比较强大,构造也比较多,非常实用
1. PrintWriter(File file)、PrintWriter(String fileName) 、PrintWriter(Filefile,String charsetName)直接使用文件作为参数,同时还能够为该次输出定义编码;
2. PrintWriter(OutputStream out)、PrintWriter(OutputStream out,booleanautoFlush) 这里使用了字节处理流作为参数,其中autoFlush即为自动刷新功能,但是需要使用他的println()方法即以换行为标记,才能体现出刷新效果。说白了自动给你flush()一下。
3. PrintWriter(Writer writer)、PrintWriter(Writer writer,boolean autoFlush)这里使用了字符处理流作为参数,同样autoFlush为自动刷新功能。
这个输出流实在太强大了,其构造非常方便我们选择性的进行输出操作,以及各种功能的选择。
BufferedReader:缓存字符输入流,内部提供了缓冲区,可以提高读取效率(其实还有一个对应的BufferedWriter缓存字符输出流,也许因为PrintWriter实在强大,感觉没必要使用这个流了)
构造:BufferedReader(Reader reader)
通过构造我们可以知道,其需要的参数是一个字符输入流,而字符输入流需要一个参数字节输入流,所以我们在新建该对象的时候至少需要套2层,才能得到该对象。
主要方法:除了一般的read()方法,该流有一个String readLine()方法 读取文件中的一行字符,以回车为标识,但是不将回车读取。返回null,则表示读完。可以使用while循环。