您的位置:首页 > 职场人生

黑马程序员-JAVA高级(IO输入与输出)PART2

2014-02-12 18:02 113 查看
----------------------
ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------

四个大知识点:

1.字符缓冲流以及装饰设计模式;

2.字节流和字节缓冲流;

3.转换流,包括读取转换流和写入转换流;

4.流操作规律。

三个小知识点:

1.改变标准输入输出设备;

2.将异常信息输出到日志文件中;

3.将系统信息输出到文本文件中。

一、字符缓冲流和装饰设计模式

缓冲区的出现是为了提高数据的读写效率。一个简单的小例子就是喝水,一滴一滴的喝不如用杯子接满再喝,杯子就是缓冲区。

1.BufferedWriter

将文本写入字符输出流,缓冲各个字符,从而提供字符、数组和字符串的高效写入。

以上代码中的几个小点:

(1)所谓“防止断电”,是指bufw对象每写一行数据就必须刷新一次,把数据写入到相应的目的地中,如果不这样,那所有数据都被暂时放在缓冲区中,如果在最后关闭流(关闭流前会刷新一次,将所有数据写入目的地)前,发生某种意外(类似于电脑断电时,如果未保存工作,那么内存中的数据都会被清空),那么所有数据就会全部消失。而如果写一次数据刷新一次,写过的数据将会得到保存。

(2)关闭缓冲流,实际上就是关闭缓冲流所操作的流,所以不必再写被操作的流关闭的代码。

(3)BufferedWriter类提供了一个跨平台的换行方法newLine()。在windows中换行符为\r\n,在linux中为\n。

2.BufferedReader

从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行(注意这里是行,BufferedWriter中是字符串)的高效读取。

以上代码中的小点:

BufferedReader类提供了一个一次读一行的方法readLine(),方便对文本数据的获取。当返回null时,表示文件读到末尾。

3.通过缓冲区复制文本

4.自定义缓冲流

以上代码中的小点:

主要是理解readLine()方法的原理,读一行归根到底还是被缓冲的流对象一个字符一个字符的读取,每读到一个字符就放入缓冲区中(在这里使用StringBuilder,实际上应使用数组),当读到换行符的时候说明达到了一行的末尾,将之前读取到的所有字符输出就是一行数据。

5.装饰设计模式

当想要给已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能提供增强的功能。该自定义的类就是装饰类。

装饰类通常会通过构造函数接收被装饰的类。

上面的缓冲类就是对应字符流的装饰类。

小例子

装饰和继承

假设MyReader是一个读取数据的类,它有两个读取不同数据类型的子类MyTexReader和MyMediaReader,体系如下

MyReader

|--MyTextReader

|--MyMediaReader

为了提高效率,想加入缓冲区,但如果每个子类都创建一个装饰类,整个体系就会显示臃肿且扩展性差,如下

MyReader

|--MyTextReader

|--MyBufferTextReader

|--MyMediaReader

|--MyBufferMediaReader

因为所有缓冲的功能都类似,改为如下代码

上面代码同样扩展性很差,如果需要缓冲的类很多的话。所以找到其参数的共同类型,通过多态的形式提高扩展性。

装饰类用于增强已有对象,具备的功能和已有对象是相同的,只不过提供了更强的功能,所以装饰类和被装饰类通常都是属于同一个体系。

最后整个体系如下

MyReader

|--MyTextReader

|--MyMediaReader

|--MyBufferReader

装饰设计模式比继承要灵活,避免了继承体系的臃肿,也降低了类与类之间的关系。

6.LineNumberReader

BufferedReader的子类,跟踪行号的字符缓冲读取流,可以设置行号和读取行号。

模拟一个带行号的缓冲类

二、字节流和字节缓冲流

1.字节流读写操作,FileInputStream和FileOutputStream

以上代码中的小点:

(1)字节输出流不用刷新方法也能将数据打印到目的地,但最后流还是必须关闭;

(2)字节输入流的available()方法须慎用,防止爆内存;

(3)字符流用的是字符数组,字节流用的是字节数组。

2.使用字节流拷贝图片

思路:

(1)用字节读取流和原图片文件相关联;

(2)用字节写入流创建一个图片文件,用来存储读取过来的数据;

(3)循环读取原文件数据,写入目标文件;

(4)关闭流,释放资源。

需要注意不要用字符流拷贝媒体文件。

3.拷贝MP3文件,使用字节流的缓冲区BufferedInputStream和BufferedOutputStream

4.自定义字节流 的缓冲区

以上代码中的小点:
为什么返回读取的字节时要“与”255?因为读到的是字节,而返回值类型是整型(4个字节),如果读到的字节是1111 1111,在字节转整型时高24位均为1,即11111111 11111111 11111111 11111111,十进制数值为-1,但此时其实并没有读到文件末尾。为了防止这种情况的发生,可以在返回值时,把得到的字节和255(即二进制00000000 00000000 00000000 11111111)做“与”运算,这样得到的整型数高24位均为0,低8位仍为原字节。

三、转换流
1.读取键盘录入
System.out:对应标准输出设备,控制台;
System.in:对应标准输入设备,键盘。
需求:通过键盘录入数据,录入一行数据后,将改行数据进行打印,如果录入的数据是over则停止录入。

发现以上代码中通过键盘录入一行数据并打印的过程就是读一行数据的原理。
2.读取转换流InputStreamReader:字节流通向字符流的桥梁
写入转换流OutputStreamWriter:字符流通向字节流的桥梁

四、流操作规律
三个明确:
1.明确源和目的
源:输入流。InputStream Reaer
目的:输出流。OutputStream Writer
2.操作的数据是否是纯文本
是:字符流。
不是:字节流。
3.明确要使用哪个具体的对象,通过设备来区分。
源设备:内存,硬盘,键盘。
目的设备:内存,硬盘,控制台

几种情况:
1.将一个文本文件的数据存储到另一个文本文件中,即复制。
分析:因为操作的数据是纯文本,所以读取用Reader,写入用Writer;因为源设备和目的设备都是硬盘,所以读取用FileReader,写入用FileWriter;要提高效率,所以读取用BufferedReader,写入用BufferedWriter。
BufferedReaer bufr = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));
2.将键盘录入的数据保存到一个文本文件中。
分析:因为操作的数据是纯文本,所以读取用Reader,写入用Writer;因为源设备是键盘,对应的System.in是字节流,所以用读取转换流InputStreamReader,目的设备是硬盘,所以写入用FileWriter;要提高效率,所以读取用BufferedReader,写入用BufferedWriter。
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new FileWriter("c.txt"));
3.按照指定的编码将一个文本文件的数据存储到另一个文本文件中。
分析:输入流情况同情况1。因为只有转换流可以指定编码,所以输出流用OutputStreamWriter;要提高效率,所以用BufferedWriter。
BufferedReaer bufr = new BufferedReader(new FileReader("a.txt"));

BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d.txt")), "UTF-8");

五、改变标准输入输出设备

System.setIn(InputStream is);//改变标准输入设备
System.setOut(PrintStream ps);//改变标准输出设备

六、将异常信息输出到日志文件中

七、将系统信息输出到文本文件中

----------------------
ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐