7.1 jvm之io字符流
字符输入流
字符输入流概括
- Level 2的输入流,大多数都会指明数据源的形式:例如CharArray,String,File
- Level 3的输入流,则不会在出现具体的数据源名字,而是以功能取代。例如:Buffered,LineNumber
- 但是和基于字节的输入流结构不同,FileInputStream是直接继承于InputStream类(基础类)的。但是FileReader却是继承于InputStreamReader的。看看下面的结构:
java.io.Reader (implements java.io.Closeable, java.lang.Readable)
java.io.BufferedReader
java.io.LineNumberReader
java.io.CharArrayReader
java.io.FilterReader
java.io.PushbackReader
java.io.InputStreamReader
java.io.FileReader_
java.io.PipedReader
java.io.StringReader
这时为什么呢?其实如果我们知道InputStreamReader的作用是什么就知道了:它的作用是充当一座基于字节流和字符流之间转换的桥梁。它将从字节流读取的字节按照编码转换成字符。
实际上任何对文件的IO读写,最终都是以字节的形式进行的。所以读取”字符”只不过是一种逻辑上的说法,那么FileReader为什么继承于InputStreamReader就可以理解了。
reader介绍
- CharArrayReader:直接从字符数组中读取数据。每次读取一个字符,存放到缓存区中。
- FileReader:从文本文件中读取字符的字符输入流,该字符输入流使用系统默认的字符集编码和缓存区大小,不能更改。如果需要重新调整输入流的编码,必须使用InputStreamReader。
- StringReader:从一个字符串中读取内容
- BufferedReader:为其它的基于字符的输入流提供缓冲功能以提高效率。通常情况下,对于底层输入流的任何一次read或者readLine请求都将导致直接的磁盘访问,这将导致效率非常地下。当使用缓存的字符输入流时,读取请求将被缓存,在合适的时候一次性读入批量数据,再进行编码转换。以此显著提高效率。这个缓存输入流的缓冲区大小是可以指定的。
- LineNumberReader:可以跟踪读入的“行数据”的字符输入流。该输入流内置一个指示器,用于跟踪读入的数据的行数。默认情况下行号从0开始。用户可以通过setLineNumber和getLineNumber来设置/或者行号。一个行可以由“换行符”,“回车符”,“回车换行符”标识。当遇到其中任意一个符号时,指示器的值将增加1。注意的是:setLineNumber方法并不会真正地改变数据在文件中的物理位置,而是简单地修改了指示器的数值而已。
字符输出流
字符输出流概括
值得注意的是:
- 在Level 2的输出流,都是以功能来命名的。例如:Print,Buffered
- 在Level 3的输出流,则多数都是以数据源的形式来命名的。例如:CharArray,File,String
所以说Level 2的输出流必须依赖于Level 3的输出流,实际上Level 2的输出流,都继承与一个叫做FilterWriter的输出流
字符输出流介绍
PrintWriter
将对象数据以恰当的格式输出到文本输出流,和PrintOutputStream类不同,后者当碰到换行符的时候会清空缓冲区。但是PrintWriter不会,它只在print方法被调用时才会清空缓存。所以理论上来说它要比PrintOutputStream更加高效,因为只要缓冲区允许,它可以接纳更多的内容而一次性写入到文件。
这个类使用系统默认的行分割符来代替“换行符"n”,因为不是所有的系统都是通过“"n”来换行的。
BufferedWriter
为其它字符输出流提供缓冲功能,该输出流的缓冲区大小可以设置,否则将使用默认的缓冲区大小。这个类有一个newLine方法,用于返回一个基于系统的行分割符,而非一定是“"n”。这个类会缓存写请求,当要写出的字符达到一定程度时就一次性地写出到底层的文件输出流。
CharArrayWriter
类似于ByteArrayOutputStream,向内存中写字符。其中内置一个缓冲区,大小可以动态增长。如果要得到写入的字符可以使用toCharArray方法,如果要构造出字符串则可以使用toString方法。
FileWriter
以基于字符的方式向文件中写数据。该输出流使用系统平台默认的字符集编码方式和缓存区大小,不能设置改变。如果需要的话可以使用OutputStreamWriter。某些系统只允许同一时刻一个文件被一个输出流打开,所以假如文件已经被另外的输出流打开了,那么新的输出流试图打开同一个文件时将抛出异常。
字节流和字符流之间的转换
- InputStreamReader:将字节流--》字符流,默认使用系统编码,可另外指定编码方式。是一个解码过程
new BufferedReader(new InputStreamReader(System.in))
- OutputStreamWriter:将字符流--》字节流,默认使用系统编码,可另外指定编码方式。是一个编码过程
new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out));