`
zsjg13
  • 浏览: 142528 次
  • 性别: Icon_minigender_1
  • 来自: 安徽
社区版块
存档分类
最新评论

Filter Streams

    博客分类:
  • io
 
阅读更多

Filter Streams:

 

InputStream和OutputStream逐个或一组字节读写。这些字节的意思是什么?——是整数或IEEE 754浮点数或Unicode文本?——这些完全由程序员和代码来决定。Java提供了一些filter类,你可以将它们对接到raw streams,实现raw bytes和其他格式间的相互转换。

(1)many intergers passed as parts of network protocols are 32-bit big-endian integers

(2)much of the text send over the Web is either 7-bit ASCII, 8-bit latin-1, or multibyte UTF-8

(3)Many files transferred by FTP are stored in the ZIP format

 

filters分2种版本:filter streams;readers and writers

(1)filter streams主要还是以字节来处理raw data

(2)readers and writers 处理各种编码的文本

 

=======1、Chaining Filters Together

Filters are connected to streams by their constructors:

 

FileInputStream     fin = new FileInputStream("data.txt");

BufferedInputStream bin = new BufferedInputStream(fin);

 

这个时候,用fin或者bin都能从文件data.txt读取数据,但不要混合用它们,因为这违背了filter streams的若干隐性的契约。Most of the time, you should only use the last filter in the chain to do the actual reading

or writing。为了避免这种问题,你可以这么写:

InputStream in = new FileInputStream("data.txt");

in = new BufferedInputStream(in);

这样,你就没法访问底层的文件输入流了。

 

但是如果有必要使用filter流中的额外方法,这些额外方法当然在超类中是没有的,那就应该这么写:

DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("data.txt")));

 

=======2、Buffered Streams

    BufferedOutputStream将写出的数据放到一个buffer中直到buffer满了或流被flushed,然后,它会将这些数据一次性写到底层的输出流上。一次写一组字节性能更高,对于网络连接就更是这样。

    BufferedInputStream内部也有一个字节数组叫作buf,当它的某个read方法被调用时 ,它首先会到buffer中去获取请求的数据,只有当buffer中没有数据时,它才到底层的源上读取。这个时候,它会从底层源上尽量多读一些数据到buffer中。

    public BufferedInputStream(InputStream in)

    public BufferedInputStream(InputStream in, int bufferSize)

    public BufferedOutputStream(OutputStream out)

    public BufferedOutputStream(OutputStream out, int bufferSize)

 

    BufferedInputStream自己没有声明任何新方法。它只是重写了InputStream中的方法。它支持marking和reseting。BufferedOutputStream同样自己也没有声明任何新方法。

 

=======3、PrintStream

    PrintStream是大多数程序员都会遇到的首个filter输出流,因为System.out就是一个PrintStream。不过,其他输出流也可以被链接到print流上,用这2个构造方法:

public PrintStream(OutputStream out)

public PrintStream(OutputStream out, boolean autoFlush)

    默认,print流应当显式flushed。然而,如果autoFlush是true,那么每次当写入一个字节数组或一个换行,或调用了println()方法,流就会被flushed。

    不但有常用的write,flush,close方法,PrintStream还有9个重载的print方法和10个重载的println方法。

每个print方法都会将其参数转换为一个字符串,然后将该字符串写到底层输出流上去,用的是默认的编码。

println做的是同样的事,只不过它还要追加一个特定于平台的行分隔符。在Unix(包括Mac OS X)上是一个linefeed(\n),在Mac OS 9上是carriage return(\r),在Windows上是carriage return/linefeed对(\r\n)

    网络程序员不要用PrintStream:

(1)第1个问题是println的输出是特定于平台的。根据你的程序在什么样的系统上运行,换行可能是linefeed或是carriage return或是carriage return/line feed对。如果是写到控制台上,这倒不是个问题,但当编写必须遵循一个精确的协议的网络客户端和服务器时就是个灾难了。大多数网络协议,如HTTP和Gnutella,它们都是指定行的中断用的是carriage return/linefeed对,所以,用println可以很容易地写出能够在Windows上正常工作的程序,但是在Unix和Mac上就会出错。尽管许多服务器和客户端能够处理不正确的行终止符,但也会有偶尔的异常发生。

(2)第2个问题是PrintStream假设的默认编码是它运行的那个平台的编码。但是这样的编码可能不是服务器或客户端所期望的。比如说,一个web浏览器接收XML文件将期望文件用UTF-8或UTF-16来编码。然而,一个使用了PrintStream的服务器,如果服务器是一个来自美国的Windows系统,那么发送的文件将用CP1252编码,如果服务器是一个来自日本的系统,那么编码就是SJIS,不管客户端是否期望就是这样的编码。PrintStream没有提供任何机制用于改变这种默认编码。

(3)第3个问题是PrintStream会吃掉所有的异常。这使得它非常适合教科书程序,例如HelloWorld,因为讲授这样的简单控制台输出,就不会要求学生们先学异常处理了。但网络肯定不比控制台稳定,所以你应该处理数据传输过程中发生的异常,但是PrintStream已经捕捉了来自底层输出流上的异常了,你会发现PrintStream中那几个标准的输出流方法并没有声明throws IOException。相反,PrintStream依靠的是一个过时的并且还是不够充分的错误标记。如果底层的流抛出一个异常,该内部标记就会被设置。程序员就需要用checkError()方法来检查这个标记。代码必须显式检查每一个调用。而且,一旦发生了一个错误,是没有办法重置这个标记的,所以后续发生的错误也没法检测了。关于错误的额外信息也是没有的。

 

=======4、Data Streams

DataInputStream和DataOutputStream提供了一些方法用于以二进制格式读写Java的原始数据类型以及String类型。用binary formats主要目的是用于在2个不同的java程序间交换数据,这2个java程序交换数据用的是一个网络连接、一个datafile、管道、或是其他中间媒介。一个数据输出流写了什么,一个数据输入流就能读入什么。然而这是恰巧大多数交换binary numbers的Internet协议用的都是相同的格式。Java和大多数网络协议都是Unix程序员设计的,因此,它们都趋向于使用Unix系统常用的格式。然而,并不是所有的网络协议都是这样的,所以你要检查一下你所使用的协议的细节。

-------------------------------DataOutputStream类提供的用于写入特定Java数据类型的方法---------------

public final void writeBoolean(boolean b) throws IOException

public final void writeByte(int b) throws IOException

public final void writeShort(int s) throws IOException

public final void writeChar(int c) throws IOException

public final void writeInt(int i) throws IOException

public final void writeLong(long l) throws IOException

public final void writeFloat(float f) throws IOException

public final void writeDouble(double d) throws IOException

public final void writeChars(String s) throws IOException

public final void writeBytes(String s) throws IOException

public final void writeUTF(String s) throws IOException

 

    所有的数据都是以big-endian格式写入的。Integers are written in two's complement in the minimum number of bytes possible。这样的话,一个byte被写为一个字节,一个shore被写为2个字节,int就是4个字节,long就是8个字节。Floats和doubles用的是IEEE 754格式,分别是4个和8个字节。Booleans是1个字节。Chars是2个unsigned字节。

    后面的3个方法,其中writeChars()就是顺序迭代那个String参数中的每个字符,写为2个字节、big-endian Unicode 字符(a UTF-16 code point, to be absolutely precise)。writeBytes()方法也是迭代String参数中的每个字符,但只是写入每个字符的least significant byte。这样,一个含有来自于Latin-1字符集之外字符的任何字符串的信息就会丢失。该方法对于一些指定ASCII编码的网络协议来说可能是有用的,但大多数时候应避免用它。

    writeChars()和writeBytes()都没有将字符串的长度编码在输出流中。结果就是,你就不能区分raw characters和那些只是一个字符串的一部分的那些characters了。writeUTF()就包含了字符串的长度信息,它将字符串本身以Unicode中的UTF-8编码来编码。由于UTF-8有点不兼容大多数非java软件,所以它只应当被用在和其他用了DataInputStream的java程序之间交换数据。要和其他软件交换UTF-8文本的话,你应当用InputStreamReader再配上合适的编码。

    DataInputStream提供了9个对应于DataOutputStream的方法,但没有提供对应writeBytes和WriteChars的方法,而是你应该通过每次读一个字节或一个字符来处理。

public final boolean readBoolean() throws IOException

public final byte readByte() throws IOException

public final char readChar() throws IOException

public final short readShort() throws IOException

public final int readInt() throws IOException

public final long readLong() throws IOException

public final float readFloat() throws IOException

public final double readDouble() throws IOException

public final String readUTF() throws IOException

    另外,DataInputStream还提供了用于读取unsigned bytes和unsigned shorts并返回等价的int值的方法,这2种数据类型,Java都没有,但你如果读取由C语言写的binary data时可能就会遇到:

public final int readUnsignedByte() throws IOException

public final int readUnsignedShort() throws IOException

    DataInputStream还提供了这几个方法:

public final int read(byte[] input) throws IOException

public final int read(byte[] input, int offset, int length) throws IOException

public final void readFully(byte[] input) throws IOException

public final void readFully(byte[] input, int offset, int length) throws IOException

用于将数据读入一个数组或子数组中,并返回它读到的字节数。起中readFully方法就是不断地从底层输入流读取数据,直到达到它请求的字节数,但是如果不能读取你要求的字节数,就会抛IOException。这样的方法是用在当你事先知道你需要读多少字节,比如,你从一个HTTP头中的Content-length字段得知了字节数。

    最后,DataInputStream还提供了一个受欢迎的readLine()方法用于读一行文本:

public final String readLine() throws IOException

但是,在任何情况下都不要使用该方法,不仅仅是它是废弃的有bug的。过时的是因为它在大多数情况下都不能正确的将non-ASSCII字符转换为bytes。该任务现在由BufferedReader来的readLine()来处理,但这2个方法都存在同样的隐秘的bug。

分享到:
评论

相关推荐

    Java高级 io 流特性

    4. **过滤流(Filter Streams)** 过滤流是一种装饰器模式的应用,可以添加额外的功能到现有的流上,如`DataInputStream`和`DataOutputStream`,它们在字节流基础上添加了对基本数据类型读写的操作。 5. **文件流...

    Java IO.pdf

    #### 九、过滤流(Filter Streams) - **过滤流**:一种特殊类型的流,用于增强其他流的功能,例如添加缓冲或转换功能。 - **缓冲流(Buffered Streams)**:通过增加缓冲区来提高读写效率。 - **PushbackInputStream**...

    JAVA程序设计-ch09.Java输入输出系统.ppt

    除了基本流,Java还提供了一种称为“过滤流”(Filter Streams)的概念,这些流可以在已存在的流之上添加额外的功能。例如,`BufferedInputStream`和`BufferedOutputStream`增加了缓冲功能,提高读写效率;`...

    IO数据流与文件处理PPT教案.pptx

    此外,流还分为节点流(Node Streams)和过滤流(Filter Streams)。节点流直接与数据源或数据宿相连,如FileInputStream和FileOutputStream,而过滤流则是在节点流基础上增加功能,如BufferedInputStream和...

    Java IO流几种经典使用方式

    #### 三、过滤器流(Filter Streams) ##### 1. 流的增强 Java中提供了多种过滤器流,它们在基础流之上添加了额外的功能或优化了性能,如`FilterInputStream`和`FilterOutputStream`。 ##### 2. 过滤器输入流...

    Java输入、输出流 、介绍

    5. **过滤流(Filter Streams)** - 过滤流是对基本流的扩展,它们添加了一些额外的功能,如缓冲、压缩、加密等。过滤流可以连接到已存在的流上,如`BufferedInputStream`和`BufferedOutputStream`可以提供缓冲功能...

    Java Network Programming 3rd Edition By Elliotte Rusty Harold 2004

    Filter Streams Section 4.4. Readers and Writers Chapter 5. Threads Section 5.1. Running Threads Section 5.2. Returning Information from a Thread Section 5.3. Synchronization Section 5.4. ...

    外文翻译—Java(译文-英文).doc

    Java的I/O系统还包括过滤流(Filter Streams),如`BufferedInputStream`和`PrintWriter`,它们可以附加到其他流上,增加额外的功能,如缓冲或格式化输出。`DataInputStream`和`DataOutputStream`允许读写基本数据...

    java课件(第7章)

    4. **输入输出类的分类**:Java的I/O类按照功能可以分为输入流、输出流、过滤流(Filter streams)、缓冲流(Buffered streams)、管道流(Piped streams)等。 5. **标准流**:Java预定义了三个标准流:`System.in...

    初级JAVA PPT教程,适用于初级学者。忘珍惜

    5. **过滤流**(Filter Streams): - 这是一类特殊的流,它们可以在已有流的基础上添加额外的功能,如压缩、加密等。例如,`FilterInputStream`和`FilterOutputStream`作为装饰者模式的实例,可以附加到任何字节流...

    java中各种流对比应用小结

    - **过滤流**(Filter Streams):包装另一个流,并在传递给该流之前增加额外的功能。 - `BufferedInputStream`/`BufferedOutputStream` #### 按照数据类型分类 - **字节流**(Byte Streams):以8位字节的形式...

    Java软件开发实战 Java基础与案例开发详解 13-5 缓冲流 共6页.pdf

    这些流都是过滤流(Filter Streams),意味着它们本身不直接操作数据源,而是包装在节点流(例如FileInputStream或FileOutputStream)之上,通过对节点流的功能进行增强来实现更高效的读写操作。 ##### 13.5.3 缓冲...

    JBuider第八章:Java.io包.rar

    过滤流(Filter Streams)提供额外的功能,如缓冲、数据压缩或加密。例如,`BufferedReader` 和 `BufferedWriter` 是过滤流,提供缓冲功能,提高效率。 5. **字符流**: 字符流包括`Reader` 和 `Writer` 类,以及...

    JDK_API_1_6_zh_CN

    3. **IO流**:Java的IO系统是基于流的,有字节流(`InputStream`和`OutputStream`)和字符流(`Reader`和`Writer`)两大类,还有过滤流(Filter Streams)、缓冲流(Buffered Streams)和转换流(InputStreamReader/...

    彻底明白 Java 语言中的IO系统 .pdf

    #### 六、为流添加属性:Filter Streams 除了基本的输入输出流外,Java还提供了`FilterInputStream`和`FilterOutputStream`,它们充当装饰器,允许在现有流的基础上添加额外功能,如缓冲、数据格式化等。例如,`...

    java IO系统与正则表达式

    此外,还有过滤流(Filter streams)如BufferedInputStream和BufferedReader,可以添加额外的功能,如缓冲、转换或压缩。 Java NIO(New IO)是Java 1.4引入的一个新特性,提供了非阻塞I/O操作,提高了多路复用的...

    java io 示例

    6. **过滤流**:过滤流(Filter Streams)是Java IO中的一个重要概念,它们是在已有流的基础上添加额外功能的流。例如,`FilterOutputStream`是所有装饰了输出流的类的基类,`FilterInputStream`也是类似。`...

    Java IO合集

    此外,过滤流(Filter Streams)如BufferedStream和PrintStream,可以添加额外的功能,如缓冲和格式化,到基本的流上。 "Java IO"这本书可能会详细解释以下内容: 1. 流的概念:字节流和字符流的区别,以及它们在...

    android一些选择题目

    - **节点流(Node Streams)** 和 **处理流(Filter Streams)** - 节点流直接与特定的I/O设备相连,如文件或网络连接。 - 处理流则用于增强或过滤节点流的功能,例如通过`FilterInputStream`或`FilterOutputStream`。...

    JAVA-IO详解.txt

    #### 五、过滤器流(Filter Streams) 过滤器流是在现有流的基础上增加功能的流。它们并不真正处理数据输入或输出,而是为其他流增加功能,例如缓冲、编码转换等。Java中常见的过滤器流有: 1. **DataInputStream*...

Global site tag (gtag.js) - Google Analytics