第15章-输入/输出 --- 处理流的用法
第15章-输入/输出 --- 处理流的用法
(一)处理流的用法
处理流可以隐藏底层设备上节点流的差异,并对外提供更加方便的输入/输出方法,让程序员只需关心高级流的操作。
我们使用处理流的典型思路是,使用处理流来包装节点流,程序通过处理流来执行输入/输出功能,让节点流与底层的I/O设备、文件交互。
识别处理流非常简单,只要流的构造器参数不是一个物理节点,而是已经存在的流,那么这种流就一定是处理流,而所有节点流都是直接以物理IO节点作为构造器参数的。
下面程序使用PrintStream处理流来包装OutputStream,使用处理流后的输出流在输出时将更加方便:
import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; public class PrintStreamTest { public static void main(String[] args) { try { FileOutputStream fos = new FileOutputStream("test.txt"); PrintStream ps = new PrintStream(fos); //使用PrintStream执行输出 ps.println("哈哈,大家好"); ps.println(new PrintStreamTest()); } catch(IOException e) { e.printStackTrace(); } } }
(二)输出/输入流体系
Java的输入/输出流体系提供了近40个类,这些类看上去杂乱而没有规律,但如果我们将其按功能进行分类,则不难发现其是非常规则的。的
下表显示了Java输入/输出流体系中常用的流分类:
从上表可以看出,Java的输入/输出流体系之所以如此复杂,主要是因为Java为了实现更好的设计,它把IO流按功能分成了许多类,而每类中又分别提供了字节流和字符流(当然有些流无法提供字节流,有些流无法提供字符流),字节流和字符流里又分别提供了输入流和输出流两大类,所以导致整个输入/输出流体系格外复杂。
下面程序示范了使用字符串作为物理节点的字符输入/输出流的用法
import java.io.StringReader; import java.io.StringWriter; public class StringNodeTest { public static void main(String[] args) { String src = "从明天起,做一个幸福的人\n" +"喂马,劈材,周游世界\n" +"从明天起,关心粮食和蔬菜\n"; char[] buffer = new char[32]; int hasRead = 0; try { StringReader sr = new StringReader(src); //采用循环读取的方式读取字符串 while((hasRead = sr.read(buffer)) > 0) { System.out.println(new String(buffer,0,hasRead)); } } catch(Exception e) { e.printStackTrace(); } try { //创建StringWriter时,实际上以一个StringBuffer作为输出节点 StringWriter sw = new StringWriter(); sw.write("有一个美丽的新世界,\n"); sw.write("她在远方等我,\n"); System.out.println("----下面是sw字符串节点里的内容----"); System.out.println(sw.toString()); } catch(Exception e) { e.printStackTrace(); } } }
输出内容:
从明天起,做一个幸福的人 喂马,劈材,周游世界 从明天起,关心粮 食和蔬菜 ----下面是sw字符串节点里的内容---- 有一个美丽的新世界, 她在远方等我,
(三)转换流
输入/输出流体系中还提供了两个转换流,这两个转换流用于实现将字节流转换成字符流,其中InputStreamReader将字节输入流转换成字符输入流,OutputStreamWriter将字节输出流转换成字符输出流。
Java没有将字符流转换为字节流的转换流,因为:字节流比字符流的使用范围更广,但字符流比字节流操作方便。如果有一个流已经是字符流了,也就是说,是一个用起来更方便的流,为什么要转换成字节流呢?反之,如果现在有一个字节流,但我们知道这个字节流的内容都是文件内容,那么把它转换成字符流来处理就会更方便一些,所以Java只提供了将字节流转换成字符流的转换流,没有提供将字符流转换成字节流的转换流。
下面以获取键盘输入为例来介绍转换流的用法:
Java使用System.in代表标准输入,即键盘输入,但这个标准输入流是InputStream类的实例,使用不太方便,而且键盘输入内容都是文本内容,所以可以使用InputStreamReader将其转换成字符输入流,普通的Reader读取输入内容时依然不太方便,我们可以将普通的Reader再次包装成BufferedReader,利用BufferedReader的readLine()方法可以一次读取一行内容。
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class KeyinTest { public static void main(String[] args) { try { //将System.in对象转换成Reader对象 InputStreamReader Reader = new InputStreamReader(System.in); //将普通的Reader包装成BufferedReaders BufferedReader br = new BufferedReader(Reader); String buffer = ""; //采用循环方式来逐渐地读取 while((buffer = br.readLine()) != null) { //如果读取的字符串为"exit",则程序退出 if(buffer.equals("exit")) { System.exit(1); } //打印读取的内容 System.out.println("输入的内容为:" + buffer); } } catch(IOException e) { e.printStackTrace(); } } }