本文原创,转载请标明原处!
流分输入流和输出流,其基本操作分别是读取和写入。
流分字节流和字符流,其操作数据分别是字节和字符。
字节流的基类:InputStream,OutputStream。
字符流的基类:Reader,Writer。
流分源头流和非源头流(嵌套流),其区别在于该流是否可以独立使用,源头流是可以独立使用的流,而非源头流是需要有源头流才能使用。下图表示出了有那些源头流。
如何认识这些流,个人觉得分六个方面认识:源头所需,性能优化,操作强化,数据过滤,多源控制,状态记录。
因源头所需而存在的流有:
- ByteArray + InputStream/OutputStream
- CharArray + Reader/Writer
- String + Reader/Writer
- File + Reader/Writer
- Piped + InputStream/OutputStream/Reader/Writer
性能优化的流主要是缓存,拥有缓存的流有:
- Buffered + InputStream/OutputStream/Reader/Writer
- LineNumberReader
- PrintWriter(注:该类可以直接使用流或文件名构造,构造的时候,会创建BufferedWriter,因此会带有缓存功能。如果使用Writer构造,就不会带有缓存功能了,因此职责单一有利于记忆和阅读,否则会造成阅读混乱,建议使用Writer参数的构造。)
操作强化是指在基本操作的基础上,增加了可以直接读取或写入实际数据的类型,拥有操作强化的流有:
- Buffered + Reader/Writer
- Print + Stream/Writer
- Data + InputStream/OutputStream
- Object + InputStream/OutputStream
数据过滤是指数据从一端流向另一端的过程中进行转换,统计,添加,删减,装饰等操作,数据过滤的流有:
- InputStreamReader:把字节转化为字符的流。
- OuputStreamWriter:把字符转化为字节的流。
- File + Reader/Writer:字节与字符间的转换。
- LineNumberReader:累计换行符的次数,即可以获取或改变当前操作的行号。
多源控制是指流不止一个数据源,一般多源是输入流才有这样的需求,拥有多源的流有:
- SequenceInputStream:从第一个源开始读取,当读取完毕时,再向第二个源读取,以此顺序读取。
- Pushback + InputStream/Reader:流一般是单向,不可逆。此流虽然可逆,但只是流向他自身的一个逆缓存。读取操作时,需要先把逆缓存的数据读取完毕,才能正式读取源。
流的基类里都带有状态记录所需的方法,分别是:markSupported,mark和reset。但并不是所有流都支持状态记录,markSupported返回布尔值就是告诉操作者,该流是否支持状态记录。
一般拥有缓存的流都支持状态记录,而部份非源头流是否支持是依赖于其源的支持。缓存流会把开始记录的数据一直存放在缓存里面,直到缓存数据的长度超出一个数值,这个数值是在调用方法mark时,传入的一个int数值,超出之后就无法回档。调用reset方法,就是把状态回档,使流从记录地方开使操作。
Filter + InputStream/OutputStream/Reader/Writer,这个流是提供给用户自定义流的模板,实现了其状态记录的支持是依赖于源。
相关:
网络输入输出,通过socket对象可以获取其输入流getInputStream()与输出流getOutputStream()。
控制台输入输出,通过System.in,System.out,System.err获取。虽然这三个对象的变量被声明为final,但可以通过System.setIn(...),System.setOut(...),System.setErr(...)方法改变。
扫描器类Scanner,这个类是继承于遍历器类Iterator<String>,并不是流,但可以使用流来创建,提供更为强大的读取能力。例如可以读取大整数BigInteger,大浮点数BigDecimal,字符串模式匹配等。
待续更新!