`
足至迹留
  • 浏览: 496923 次
  • 性别: Icon_minigender_1
  • 来自: OnePiece
社区版块
存档分类
最新评论

<3> Filter Stream & Data Stream & Streams in memory

阅读更多
六、Filter Streams
Filter input Streams从预先存在的输入流(比如FileInputStream)中读取数据,在把数据发送给客户端程序之前可以对数据进行预处理。Filter output Streams把数据写到预先存在的输出流(比如FileOutputStream)里,可以在把数据写到底层的输出流之前再加工数据。一个底层的stream之上可以叠加多个filter。Filter Stream可以用来完成加密,压缩,缓存等操作。

Filter一词来源于滤水器(water filter)。 滤水器位于水管和水源之间,stream filter位于数据源和最终的目的地之间,在此间可以使用特定的算法处理数据。

6.1 The Filter Stream Classes
java.io.FilterInputStream和java.io.FilterOutputStream是各具体filter stream实现类的父类。
public class FilterInputStream extends InputStream 
public class FilterOutputStream extends OutputStream

这两个类都有一个protected的构造方法,必须指明要进行预处理的底层的stream(specify the underlying stream from which the filter stream reads or writes data)。
protected FilterInputStream(InputStream in)
protected FilterOutputStream(OutputStream out)
指定的底层stream会被分别保存到protected的成员变量里:
protected InputStream in
protected OutputStream out
因为这两个类的构造方法是protected的,所以只能由子类来创建具体的对象(Filter Stream classes 的实现实际上是装饰器模式的应用)。

FilterOutputStream的close()方法实现如下:
public void close() throws IOException 
{ 
    out.close(); 
}

因此,关闭一个filter stream也就是关闭了底层实际的stream,无论是Filter inputstream还是OutputStream,也无论嵌套几层Filter stream都是这样。

6.2 The Filter Stream Subclasses
java.io包里有很多有用的filter stream classes. BufferedInputStream和BufferedOutputStream类会把读和写的数据首先放到缓存里。因此,应用程序可以不用调用底层数据流的native方法就可以读或写数据。很多情况下这可以提高性能。

java.io.PrintStream类(System.out和System.err就是这个类型的)可以简单的打印出原始类型值,对象和字符串。这个类使用平台默认的字符编码来转换字符成bytes。我们也能用PrintStream当做过滤器作用在其他outputStream上,比如作用在FileOutputStream上就可以简单的输出文本到文件中。

DataInputStream和DataOutputStream类可以用机器独立(machine-independent way)的方式来读和写java原始数据类型。(Big-endian for integer types, IEEE-754 for floats and doubles, UTF-8 for Unicode)。

6.3 Buffered Streams
Buffered input Streams会读比原始需要要多的数据到一个缓存里(一个内部的byte数组)。当调用Stream的read()方法时,首先会从缓存里获取数据而不是底层的stream, 当缓存的数据用完时,buffered stream会再次从底层stream里读一块数据填满缓存。同样地,buffered output stream在一个内部byte数组里存储数据,直到缓存满了或显式调用flush()方法数据才会一下子输出到底层output stream.

BufferedInputStream和BufferedOutputStream分别有两个构造方法:
public BufferedInputStream(InputStream in) 
public BufferedInputStream(InputStream in, int size) 
public BufferedOutputStream(OutputStream out) 
public BufferedOutputStream(OutputStream out, int size)

第一个参数是底层实际的stream, 第二个参数size就是缓存的大小。如果不指定缓存size, 默认使用2048字节的缓存。缓存大小最好根据平台来定,或者最好跟硬盘的block大小相关。 小于512字节可能会太小,大于4096可能会太多。对于不可靠的网络连接,最好使用较小的缓存大小:
URL u = new URL("http://java.developer.com"); 
BufferedInputStream bis = new BufferedInputStream(u.openStream(), 256);


七、Data Streams
Data stream能读和写string,integer, float和其他数据类型数据。java.io.DataInputStream和java.io.DataOutputStream类以一种平台独立的方式读和写原始数据类型(boolean, int,double等)。

7.1 The Data Stream Classes
java.io.DataInputStream和java.io.DataOutputStream类是FilterInputStream和FilterOutputStream的子类:
public class DataInputStream extends FilterInputStream implements DataInput 
public class DataOutputStream extends FilterOutputStream implements DataOutput	


7.1.1 The DataInput and DataOutput Interfaces
java.io.DataInput接口声明了15个读各种各样数据的方法:
public abstract boolean readBoolean() throws IOException 
public abstract byte readByte() throws IOException 
public abstract int readUnsignedByte() throws IOException 
public abstract short readShort() throws IOException 
public abstract int readUnsignedShort() throws IOException 
public abstract char readChar() throws IOException 
public abstract int readInt() throws IOException 
public abstract long readLong() throws IOException 
public abstract float readFloat() throws IOException 
public abstract double readDouble() throws IOException 
public abstract String readLine() throws IOException 
public abstract String readUTF() throws IOException 
public void readFully(byte[] data) throws IOException 
public void readFully(byte[] data, int offset, int length) throws IOException 
public int skipBytes(int n) throws IOException


类似地,java.io.DataOutput接口声明了14个方法,大部分是跟DataInput接口对应的:
public abstract void write(int b) throws IOException 
public abstract void write(byte[] data) throws IOException 
public abstract void write(byte[] data, int offset, int length) throws IOException 
public abstract void writeBoolean(boolean v) throws IOException 
public abstract void writeByte(int b) throws IOException 
public abstract void writeShort(int s) throws IOException 
public abstract void writeChar(int c) throws IOException 
public abstract void writeInt(int i) throws IOException 
public abstract void writeLong(long l) throws IOException 
public abstract void writeFloat(float f) throws IOException 
public abstract void writeDouble(double d) throws IOException 
public abstract void writeBytes(String s) throws IOException 
public abstract void writeChars(String s) throws IOException 
public abstract void writeUTF(String s) throws IOException


注意这里的writerBytes()和writeChars()方法跟DataInput的readBytes()和readChars()方法不是对应匹配的。下面是DataInput和DataOutput的方法的对应关系:




7.1.2 Constructors
DataInputStream和DataOutputStream的构造方法如下:
public DataInputStream(InputStream in) 
public DataOutputStream(OutputStream out)

使用示例:
DataInputStream dis = new DataInputStream(new FileInputStream("data.txt")); 
DataOutputStream dos = new DataOutputStream(new FileOutputStream("output.dat"));


八、Streams in Memory
前面介绍的输入输出主要是在java程序和外部程序之间。本章再扩展三个类似的方法。Sequence input streams能把好几个input streams串在一起好像是一个stream一样;
Byte array streams能把数据存储在byte arrays里也能从byte arrays里读数据;
最后,piped input and output streams可以让一个线程的输出称为一个线程的输入。

8.1 Sequence input Streams
java.io.SequenceInputStream类以一定的顺序连接多个input stream:
public class SequenceInputStream extends InputStream
从SequenceInputStream里读数据会先从第一个stream里读取所有数据,然后读取第二个stream的所有数据,以此类推直到最后一个stream的所有数据,这个类有两个构造方法:
public SequenceInputStream(Enumeration e) 
public SequenceInputStream(InputStream in1, InputStream in2)


示例:
try
{ 
    URL u1 = new URL("http://java.sun.com/"); 
    URL u2 = new URL("http://www.altavista.com"); 
    SequenceInputStream sin = new SequenceInputStream(u1.openStream(), 
    u2.openStream()); 
} 
catch (IOException e)
{ //...


8.2 Byte Array Streams
有时候使用stream的方法操作byte arrays里的数据很方便。比如,我们可能接收到一个原始字节的数组,里面的数据需要解释成double类型。最快的方式是使用DataInputStream,但是在创建DataInputStream之前,我们首先需要创建一个原始的byte流才能接收字节数据,这正是java.io.ByteArrayInputStream类提供的能力。

8.2.1 Byte Array Input Streams
ByteArrayInputStream类使用InputStream的方法从byte array里读数据:
public class ByteArrayInputStream extends InputStream
此类有两个构造方法,参数就是数据源:
public ByteArrayInputStream(byte[] buffer) 
public ByteArrayInputStream(byte[] buffer, int offset, int length)


8.2.2 Byte Array Output Streams
ByteArrayOutputStream类使用java.io.OutputStream的方法输出数据到byte array.
public class ByteArrayOutputStream extends OutputStream
它有两个构造方法:
public ByteArrayOutputStream() 
public ByteArrayOutputStream(int size)

无参构造方法使用一个32字节的buffer.使用toByteArray()方法能返回包含要输出数据的byte数组:
public synchronized byte[] toByteArray()

这个类也有toString()方法能把bytes转成string。无参的版本使用平台默认的编码,第二个方法可以自己指定编码。
public String toString() 
public String toString(String encoding) throws UnsupportedEncodingException


比如,一个把double转成bytes的方法就是用DataOutputStream过滤类嵌套在ByteArrayOutputStream外面,然后输出double到byte array:
ByteArrayOutputStream bos = new ByteArrayOutputStream(1024); 
DataOutputStream dos = new DataOutputStream(bos); 

for (int r = 1; r < 1024; r++)
{ 
    dos.writeDouble(r * 2.0 * Math.PI); 
}


8.3 Communicating Between Threads with Piped Streams
java.io.PipedInputStream类和java.io.PipedOutputStream类提供了方便的方法来把stream在线程之间传递。

public class PipedInputStream extends InputStream 
public class PipedOutputStream extends OutputStream


PipedInputStream有两个构造方法:
public PipedInputStream()
public PipedInputStream(PipedOutputStream source) throws IOException
无参的构造方法创建一个还没有和一个piped outputStream关联的piped InputStream。第二个构造方法创建一个已经和一个output stream连接的piped input Stream。
同样,PipedOutputStream也有两个构造方法:
public PipedOutputStream(PipedInputStream sink) throws IOException
public PipedOutputStream()

使用示例:
PipedOutputStream pout = new PipedOutputStream(); 
PipedInputStream pin = new PipedInputStream(pout);
PipedInputStream pin = new PipedInputStream(); 
PipedOutputStream pout = new PipedOutputStream(pin);


或者创建两个都没有关联的输入输出之后再连接:
PipedInputStream pin = new PipedInputStream(); 
PipedOutputStream pout = new PipedOutputStream(); 
pin.connect(pout);


参考:
《java I/O》 Elliotte Rusty Harold
  • 大小: 88.7 KB
  • 大小: 160 KB
  • 大小: 78.7 KB
0
0
分享到:
评论

相关推荐

    Mastering Lambdas- Java Programming in a Multicore World

    The Stream API in Java is designed to process collections (and arrays) of data efficiently. It supports three main types of operations: - **Intermediate Operations**: These operations return a new ...

    eac3to V3.17

    * log file now contains "&lt;WARNING&gt;" and "&lt;ERROR&gt;" indicators * workaround for movie playlists which want the same m2ts file played twice * added version check for eac3to (doh!) * when a read error ...

    python3.6.5参考手册 chm

    Data Instead Of Unicode Vs. 8-bit Overview Of Syntax Changes New Syntax Changed Syntax Removed Syntax Changes Already Present In Python 2.6 Library Changes PEP 3101: A New Approach To String ...

    Python Cookbook, 2nd Edition

    Interpolating Variables in a Stringin Python 2.4 Recipe 1.18. Replacing Multiple Patterns in a Single Pass Recipe 1.19. Checking a String for Any of Multiple Endings Recipe 1.20. Handling ...

    php.ini-development

    will send that data in chunks of roughly the size you specify. ; Turning on this setting and managing its maximum buffer size can yield some ; interesting side-effects depending on your application ...

    PHP5 完整官方 中文教程

    Streams — Stream Functions Strings — String 字符串处理函数 SVN — Subversion 函数 SWF — Shockwave Flash Functions swish — Swish Functions Sybase — Sybase Functions TCP Wrappers — TCP Wrappers ...

    PHP5中文参考手册

    Streams — Stream Functions Strings — String 字符串处理函数 SVN — Subversion 函数 SWF — Shockwave Flash Functions swish — Swish Functions Sybase — Sybase Functions TCP Wrappers — TCP Wrappers ...

    PHP官方手册中文版

    53. Working with streams 54. PDO Driver How-To 55. Extension FAQs 56. Zend Engine 2 API reference 57. Zend Engine 1 58. The future: PHP 6 and Zend Engine 3 VIII. FAQ:常见问题 59. 一般信息 60....

    PHP手册2007整合中文版

    53. Working with streams 54. PDO Driver How-To 55. Extension FAQs 56. Zend Engine 2 API reference 57. Zend Engine 1 58. The future: PHP 6 and Zend Engine 3 VIII. FAQ:常见问题 59. 一般信息 60. 邮件...

Global site tag (gtag.js) - Google Analytics