我们知道Java中的流分为字符流和字节流,其中字符流主要针对字符文本进行处理,而字节流处理范围更为广泛,毕竟图片、电影等只要是文件都是以二进制的形式存在的,而不是字符。
字符流:
FileReader
FileWriter。
BufferedReader
BufferedWriter
字节流:
FileInputStream
FileOutputStream
BufferedInputStream
BufferedOutputStream
我们看一下J2SE文档:
BufferedReader(Reader in):创建一个使用默认大小输入缓冲区的缓冲字符输入流。
可以看出BufferedReader是一个Reader的子类,构造函数传进来的是父类Reader类,其实是装饰者模式,将父类比较低效的读取数据的方式做成了比较高效的缓冲区读取方式。
String
readLine():读取一个文本行。
它有一个方法readLine(),直接读取一行,相对于父类Reader的read()方法更加方便。
System.in:对应的标准输入设备:键盘。
static InputStream in :“标准”输入流。
我们可以写一个类来使用System中的静态方法in来从键盘读取数据:
import java.io.*; class ReadIn{ public static void main(String[] args) throws IOException{ InputStream inin = System.in; //新建一个InputStream对象,读取位置为键盘 StringBuilder sb = new StringBuilder(); //用于存储读入的字符,相当于自己建了一个缓存区 while(true){ int ch = inin.read(); //读取字节 if(ch=='\r') continue; if(ch=='\n'){ String s = sb.toString();//读到回车符就转成String,看看是否是"over",是就退出度数 if("over".equals(s)) break; else{ System.out.println(s.toUpperCase());//不是"over"的话就不退出,一行读取完毕,输出到屏幕上 sb.delete(0,sb.length()); //清空缓存StringBuilder sb } } else sb.append((char)ch); //如果没读到换行符,就继续往缓存StringBuilder里添加读取的字符 } } }
System的in的类型是InputStream,属于字节流,和BufferedReader属于不同的流类。在InputStream中没有readLine()这样的整行读取方法,只有read()。
那么能不能直接使用readLine()方法来完成键盘录入的一行数据的读取呢?
即“能不能将字节流转成字符流,然后再使用字符流缓冲区的readLine方法呢”?
可以的!
在字符流中有这样的字符流:
将字节流转换成字符流的桥梁——InputStreamReader;
InputStreamReader(InputStream in) :创建一个使用默认字符集的 InputStreamReader。传入的对象是InputStream类型,而自己本身是Reader的子类。
将字符流转换成字节流的桥梁——OutputStreamWriter。
OutputStreamWriter(OutputStream out) :创建使用默认字符编码的 OutputStreamWriter。传入的对象是OutputStream类型,而自己本身是Writer的子类。
从名字就可以看出,他们分别属于(从属关系看名字的后半部分)字符流Reader和Writer,他们的功能(功能看名字的前半部分)和字节流InputStream、OutputStream相关。
import java.io.*; class TransStreamDemo{ public static void main(String[] args) throws IOException{ InputStream in = System.in; //获取键盘录入对象。 InputStreamReader isr = new InputStreamReader(in); //将字节流对象转成字符流对象,使用转换流。InputStreamReader BufferedReader bufr = new BufferedReader(isr); //为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader // BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in)); //最常见写法,以后都这样写!!! OutputStream out = System.out; OutputStreamWriter osw = new OutputStreamWriter(out); BufferedWriter bufw = new BufferedWriter(osw); // BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out)); //同上!!! String line = null; while( ( line = bufr.readLine() ) != null ){ if("over".equals(line)) break; bufw.write(line.toUpperCase()); //bufw将osw包装了,osw将out包装了,本例中out是Syetem.out的对象实现,所以原本用System.out.println的地方直接可以用包装后的bufw输出字符串。 bufw.newLine(); //输出换行符:可以根据Linux和Windows的不同自动输出\n或\r\n bufw.flush(); //输出流有缓冲区,需要flush才输出来 } bufr.close(); } }