关于原始流与字符流之间的转换中的设计问题
装饰模式在这里显然派上了很大的用用场,现在先分析一下InputStramReader到底是如何将原始流包装成字节流的。
明显他们中间的主接口是 InputStream,这个接口主导了其中的设计,使各个类之间能够方便被相互修饰,说白了还是装饰模式。
比较不解的地方就是在使用 OutputStreamWrite中的write(byte[] b, int off, int len);中的方法的时候会莫名错误(当然错误的提示很明确,但是我查看过java.io.OutputStreamWriter类的源码之后发现一个很奇怪的问题),莫名的原因就是因为在查看 java.io.OutputStreamWriter的源码的时候发现,其中的weite(byte[]b, int off,int len)方法的参数竟然是一个StreamEncoder类型的,经过我查看其中的类型发现StreamEndcoder是com.sun.nio包下的一个类,其实不是特别清楚,想去查看源码,但是发现竟然没有com.sun这个包,然后就很不解了,忘指点。
其他的关于IO流的东西,已经比较清楚了,我希望可以用java做出来一些特例独行,和别人不一样的东西,最近在设计的网站雏形还没有出来,更是没时间做,主导开发还是php,所以近期压力比较大,也不能说压力大吧,随便看一下而已。
如果老师们看一看 thinking in java之后可以模仿上面的方法来教导学生,其实如果只是想知道语法和基础的东西的话自己看就可以了,我更希望得到切实的经验,因为对一个不聪明的人来说,经验是最宝贵的,尤其是自己得不到的经验
下面是一篇比较好的概述,方便以后查看
Java中的流、字符流和字节流
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明http://sobaid.blogbus.com/logs/59873645.html
一、什么是流:
流是一个抽象的概念。当Java程序需要从数据源读取数据时,会开启一个到数据源的流。数据源可以是文件,内存或者网络等。同样,当程序需要输出数据到目的地时也一样会开启一个流,数据目的地也可以是文件、内存或者网络等。流的创建是为了更方便地处理数据的输入输出。
流分为字节流和字符流。字节流也称为原始数据,需要用户读入后进行相应的编码转换。而字符流的实现是基于自动转换的,读取数据时会把数据按照JVM的默认编码自动转换成字符。
字节流由InputStream和OutputStream处理,而字符流由Reader和Writer处理。Reader和Writer是Java后加入的处理类,出于让数据的处理更方便的目的。
二、字节流和字符流
如果数据流中最小的数据单元是字节,那么称这种流为字节流;如果数据流中最小的数据单元是字符,那么称这种流为字符流。在Java的IO系统中,java.io.InputStream和java.io.OutputStream分别表示字节输入流和字节输出流,java.io.Reader和java.io.Writer分别表示字符输入流和字符输出流。
I/O流的层次
1.字节流:
从InputStream和OutputStream派生出来的一系列类。这类流以字节(byte)为基本处理单位。
◇ InputStream、OutputStream
◇ FileInputStream、FileOutputStream
◇ PipedInputStream、PipedOutputStream
◇ ByteArrayInputStream、ByteArrayOutputStream
◇ FilterInputStream、FilterOutputStream
◇ DataInputStream、DataOutputStream
◇ BufferedInputStream、BufferedOutputStream
2.字符流:
从Reader和Writer派生出的一系列类,这类流以16位的Unicode码表示的字符为基本处理单位。
◇ Reader、Writer
◇ InputStreamReader、OutputStreamWriter
◇ PipedReader、PipedWriter
◇ FileReader、FileWriter
◇ CharArrayReader、CharArrayWriter
◇ FilterReader、FilterWriter
◇ BufferedReader、BufferedWriter
◇ StringReader、StringWriter
3.对象流
◇ ObjectInputStream、ObjectOutputStream
4.其它
◇ 文件处理:
File、RandomAccessFile;
◇ 接口
DataInput、DataOutput、ObjectInput、ObjectOutput
三、字节流
1. 处理概述:
对于字节流处理的类都继承自InputStream和OutputStream这两个抽象类。
InputStream提供的最重要的方法是:
Java代码
1. read();
2. read(byte[] b) ;
3. read(byte[] b, int off, int len) ;
用于从输入流中读取字节。
OutputStream提供的最重要的方法是:
Java代码
1. write(int b);
2. write(byte[] b);
3. write(byte[] b, int off, int len)
用于将字节写入输出流。
2. 字节流:
字节流的处理类有很多,他们都继承自InputStream或者OutputStream抽象类。
输入流:
先谈谈输入流,输入流中跟数据源直接接触的类有:FileInputStream和ByteArrayInputStream,他们分别实现了从文件或者内存中的字节数组读入数据到输入流。
其他的输入流处理类都是装饰类(Decorator模式),下面对他们进行一下简单介绍:
BufferedInputStream: 提供了缓冲功能。
DataInputStream: 允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。
PipedInputStream: 允许以管道的方式来处理流。当连接到一个PipedOutputStream后,它会读取后者输出到管道的数据。
PushbackInputStream: 允许放回已经读取的数据。
SequenceInputStream: 能对多个inputstream进行顺序处理。
输出流:
基本上每个输入流类都有一个相应的输出流类,提供相应的输出流处理。
同样,跟数据目的地直接接触的类有:FileOutputStream和ByteArrayOutputStream,前者实现了把数据流写入文件的功能,后者实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray() 和 toString() 获取数据。
下面对其它的装饰类做一下简单介绍:
BufferedOutputStream: 提供了缓冲功能的输出流,在写出完成之前要调用flush来保证数据的输出。
DataOutputStream: 数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。
PipedOutputStream: 允许以管道的方式来处理流。可以将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端。通常,数据由某个线程写入 PipedOutputStream 对象,并由其他线程从连接的 PipedInputStream 读取。
PrintStream: 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。我们经常用到的System.out或者System.err都是PrintStream。
四、字符流:
1. 字符流处理概述
所有的字符流操作类都继承自Reader或者Writer这两个抽象类。
Reader提供的重要方法有:
Java代码
1. read(char[] cbuf);
2. read(char[] cbuf, int off, int len);
3. read(CharBuffer target);
他们提供了从流中读取数据到字符数组或者CharBuffer的功能。
Writer提供的重要方法有:
Java代码
1. write(char[] cbuf);
2. write(char[] cbuf, int off, int len);
3. write(int c);
4. write(String str);
write(String str, int off, int len);
他们提供了把字符、字符数组或者字符串写入流中的功能。
2. 字符流处理
输入流:
跟数据源直接接触的类:
CharArrayReader: 从内存中的字符数组中读入数据,以对数据进行流式读取。
StringReader:从内存中的字符串读入数据,以对数据进行流式读取。
FileReader:从文件中读入数据。注意这里读入数据时会根据JVM的默认编码对数据进行内转换,而不能指定使用的编码。所以当文件使用的编码不是JVM默认编码时,不要使用这种方式。要正确地转码,使用InputStreamReader。
装饰类:
BufferedReader:提供缓冲功能,可以读取行:readLine();
LineNumberReader: 提供读取行的控制:getLineNumber()等方法。
InputStreamReader: 字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。
输出流:
根数据目的相关的类:
CharArrayWriter:把内存中的字符数组写入输出流,输出流的缓冲区会自动增加大小。输出流的数据可以通过一些方法重新获取。
StringWriter: 一个字符流,可以用其回收在字符串缓冲区中的输出来构造字符串。
FileWriter:把数据写入文件。
装饰类:
BufferedWriter:提供缓冲功能。
OutputStreamWriter:字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。
PrintWriter: 向文本输出流打印对象的格式化表示形式。
流处理中的其它方法:
mark和reset用于重复读取某段的数据,如下代码:
Java代码
1. is = new BufferedInputStream(new FileInputStream("res/input.data"));
2. assertTrue(is.available() > 0);
3. assertTrue(is.markSupported());
4. // The read limit has no effect.
5. is.mark(0);
6. int first = is.read();
7. int second = is.read();
8. is.reset();
9. int firstAgain = is.read();
10. int secondAgain = is.read();
11. assertEquals(first, firstAgain);
12. assertEquals(second, secondAgain);
Writer或者OutputStream中的flush(): 刷新该流的缓冲,用于确保数据的输出。
close(): 关闭流并释放与之关联的所有系统资源。