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

黑马程序员-Java语言基础– IO流 第19天

2012-06-24 01:00 417 查看
---------------------- android培训java培训、期待与您交流!
----------------------

字符流的缓冲区

缓冲区是为了提高流的操作效率而出现的,所以再创建缓冲区之前,必须要先有流对象。 对应类:

BufferedWriter //将文本写入字符输出流,缓冲各个字符。

BufferedReader//从字符输入流中读取文本,缓冲各个字符。

缓冲区要结合流才可以使用。在流的基础上对流的功能进行了增强。

只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。

只要用到缓冲区,就要记得刷新。

bufw.close();(其实关闭缓冲区就是在关闭缓冲区中的流对象。)

换行:该缓冲区中提供了一个跨平台的换行符。newLine();

BufferedWriter类的newLine()换行方法是跨平台的的。

bufw.newLine();//相当于bufw.write(\r\n);

字符读取流缓冲区

该缓冲区提供了一个一次读取一行的方法,readLine。方便于对文本数据的获取。当返回空时,即读到文件末尾。

步骤:

1、创建一个读取流对象和文件相关联。

FileReader fr = newFileReader("buf.txt");

2、为了提高效率,加入缓冲技术,将字符读取流对象作为参数传递给缓冲对象的构造函数。

BufferedReader bufr = newBufferedReader(fr);

FileReader fr = new FileReader("buf.txt");

BufferedReader bufr = new BufferedReader(fr);

String line = null;

while ((line=bufr.readLine())!=null)

{

System.out.println(line);

}

BufferedReader类的readLine()方法是读一整行,读到末尾返回null,返回内容不包含任何行终止符。其原理最终使用的还是read方法一次读一个。[day19-2]

装饰设计模式

[day19-06]

当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强的功能,那么自定义的该类就称为装饰类。(装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰对象的功能,提供更强的功能。)

装饰与继承有什么不同?

1、装饰模式比继承要更灵活,避免了继承体系臃肿,而且降低了类与类之间的关系。

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

MyReader//专门用于读取数据的类。

|--MyTextReader

|--MyBufferTextReader

|--MyMediaReader

|--MyBufferMediaReader

|--MyDataReader

|--MyBufferDataReader

class MyBufferReader

{

MyBufferReader(MyTextReader text)

{}

MyBufferReader(MyMediaTextReader media)

{}

}

上面这个类扩展性很差。

找到其参数的共同类型,通过多态的形式,可以提高扩展性。

class MyBufferReader extends MyReader

{

private MyReader r;

MyBufferReader(MyReader r)

{}

}

MyReader//专门用于读取数据的类。

|--MyTextReader

|--MyMediaReader

|--MyDataReader

|--MyBufferReader

LineNumberReader:跟踪行号的缓冲字符输入流,默认行号从0开始。

setLineNumber(int);

getLineNumber();

字节流:

基本操作与字符流类相同。操作文本,媒体文件等。

InputStream (读)

FileInputStream fis = newFileInputStream(“fos.txt”);

OutPutStream(写 凡是输出的都是写)

FileOutputStream fos = newFileOutputStream(“fos.txt”);

“abcde”.getBytes();//字符串变为字节数组。

“abcde”.toCharArray();

byte[] buf = new byte[1024]; //缓冲数组。不建议用以下格式。

byte[] buf = new byte[fis.available()];//定义一个刚刚好的缓冲区。不用再循环.

字节流的缓冲区:

BufferedInputStream

BufferedOutputStream

同样是提高了字节流的读写效率。

read()方法在提升,write在强转。只将最低八位(一个字节)写出去。

字节流的读一个字节的read方法为什么返回int而不是byte?[day19-14]

因为有可能会读到连续8个二进制1,而8个二进制1对应的十进制是-1,那么就会发生数据还没读完就结束的情况,因为我们是通过结尾标记-1来判断读取是否结束的。

所以,为了避免这种情况的发生,将读到的字节进行int类型提升,并在保留原字节数据的情况下在高位补了24个0,变为int类型的数值,而在写入时数据时,只写入该int类型数据的最低8位。

int数据类型在计算机里面占用4个字节一个字节是8个二进制位,1 int = 4 * byte

当用输入流读取一些媒体、图像文件时,这些文件里的数据正是常说的二进制数据即:01串

那么用read()读取文件数据时是一个字节一个字节读取的,读一个字节相当于读了八个二进制位,因已到达流末尾而没有可用的字节,则返回值 -1.而文件中任何一个字节位置都有可能是11-11-11-11八个一,

11-11-11-11这是一个字节这个字节转换成十进制时表示-1,-1用一个int类型来接收是被提升了还是-1,但是用四个字节来表示即:

11111111-->11111111-11111111-11111111-11111111,

如果提升的时候前面不补1补0,这时候表示-1的一个字节被提升到int类型4个字节就不是-1了,即:255

11111111-->00000000-00000000-00000000-11111111

那么只要在前面补0,既可以保留原字节数据不变,又可以避免-1的出现。

接下来就是怎样才能按前面补0这种方法将独到的字节提升到int类型的呢?

11111111-11111111-11111111-11111111

&00000000-00000000-00000000-11111111

-------------------------------------------------

00000000-00000000-00000000-11111111

即将读取的那个字节&上255即可。

因此RandomAccessFile.read()只读的是一个字节返回的是一个int

IO流类型及其子类

字符流:

Reader Writer

FileReader

FileWriter

BufferedReader

BufferedWriter

字节流:

InputStream OutPutStream

FileInputStream

FileOutPutStream

BufferedInputStream

BufferedOutPutStream

转换流:

InputStreamReader是字节流通向字符流的桥梁。

OutputStreamWriter是字符流通向字节流的桥梁。(录入字符,存为字节的形式)

以上本身是字符流。

转换流的由来:

·字符流与字节流之间的桥梁。

·方便了字符流与字节流之间的操作。

转换流的应用:

·字节流中的数据都是字符时,转成字符流操作更高效。

标准输入输出流:

System类中的字段:in,out。

它们各代表了系统标准的输入和输出设备。

默认输入设备是键盘in,输出设备是显示器out。

System.in的类型是InputStream。

System.out的类型是PrintStream是OutputStream的子类FilterOutputStream的子类。

标准输入输出流示例:[day19-16]

例: 获取键盘录入数据,然后将数据流向显示器,那么显示器就是目的地。

通过System类的setIn,setOut 方法对默认设备进行改变。

System.setIn(newFileInputStream(“1.txt”));//将源改成文件1.txt 。

System.setOut(newFileOutputStream(“2.txt”));//将目的改成文件2.txt

因为是字节流处理的是文本数据,可以转换成字符流,操作更方便。

常见键盘录入与输出:

BfferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

BufferedWriter bufw = new BufferedWriter(newOutputStreamWriter(System.out));

/*

//获取键盘录入对象。

InputStream in = System.in;

//将字节流对象转成字符流对象,要使用转换流 InputStreamReader

InputStreamReader isr = new InputStreamReader(in);

//为了提高效率,将字符串进行缓冲区技术高效操作,使用BufferedReader。

BufferedReader bufr = new BufferedReader(isr);

*/

//以上三句话变为一句

//键盘录入最常见写法。

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));

流的基本应用小节

·流是用来处理数据的。

·处理数据时,一定要先明确数据源,与数据目的地(数据汇)。

·数据源可以是文件,可以是键盘。

·数据目的地可以是文件、显示器或者其他设备。

·而流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理.转换处理等。

流操作规律:[day19-21]强烈推荐多看几遍

最痛苦的就是流对象很多,不知道该用哪一个。

通过三个明确来完成:

1、明确源和目的。

源:输入流,InputStream,Reader。

目的:输出流,OutputStream,Writer。

2、明确要操作的数据是否是纯文本。

是:字符流。

不是:字节流。

3、明确体系后,再明确要使用那个具体的对象,通过设备来进行区分:

源设备:内存,硬盘,键盘。

目的设备:内存,硬盘,控制台。

只有转换流可以指定编码表,所以通常涉及到字符编码转换时,需要用转换流。

FileReader和FileWriter都是使用默认字符编码的。

记住,转换流什么时候使用,字符和字节之间的桥梁,通常,涉及到字符编码转换时,需要用到转换流。

---------------------- android培训java培训、期待与您交流! ----------------------

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