Java I/O全文摘要(九)過濾流,內存流

1 內存流

之前的章節中,講述瞭如何從Java程序的一個數據源移動數據到另一個數據源。流還可以從Java程序的一個部分移動數據到另一個部分。

本章講解下面這些流:

Sequence stream,Byte array stream, Piped stream

Sequence stream:將多個流合成單一流。

Byte array stream:將輸出儲存在字節數組中或者從字節數組中讀出數據。


2 序列輸入流

可將多個流合成一個流:

合併兩個流:

public SequenceInputStream(InputStream in1, InputStream in2)

合併一組流:

public SequenceInputStream(Enumeration<? extends InputStream> e)

之所以是Enumeration是因爲這個在1.0時代就有了,在5.0時加上了泛型限制。


樣例:你可以創建兩個流,然後將其放入序列流,這樣,你使用起來就像一個流。

URL u1 = new URL("http://www.yahoo.com/");
URL u2 = new URL("http://www.google.com");
SequenceInputStream sin = new SequenceInputStream(
  u1.openStream(), u2.openStream( ));


3 字節數組輸入流

構造方法:

public ByteArrayInputStream(byte[] buffer)
public ByteArrayInputStream(byte[] buffer, int offset, int length)


從byte[]中讀取數據,然後生成流。


4 字節數組輸出流

構造方法:

public ByteArrayOutputStream( )
public ByteArrayOutputStream(int size)
默認爲32byte.

這個是將內存中的數據寫出去。但是默認情況下,並沒有寫出去的地方,爲了解決這個問題:

使用本身的writeTo( )方法:

public void writeTo(OutputStream out) throws IOException

例如,你可以先使用過濾流進行裝飾:

ByteArrayOutputStream bout = new ByteArrayOutputStream(howMany*4);
    DataOutputStream dout = new DataOutputStream(bout);

然後使用writeTo方法,指定輸出:

    FileOutputStream fout = new FileOutputStream("fibonacci.dat");
    try {
      bout.writeTo(fout);
      fout.flush( );
    }
    finally {
      fout.close( );
    }

5 使用管道流在線程中通信


java.io.PipedInputStream  和java.io.PipedOutputStream提供了一些便利的方法在線程直接進行數據的搬運操作。


它的構造方法如下:

public class PipedInputStream  extends InputStream
public class PipedOutputStream extends OutputStream

他們都具有無參和依賴對方的構造方法:

public PipedOutputStream(PipedInputStream sink) throws IOException
public PipedOutputStream( )

PipedOutputStream pout = new PipedOutputStream( );
PipedInputStream  pin  = new PipedInputStream(pout);

你可以再同一個線程中使用他們。

如果你在最初沒有建立兩者的聯繫,可以使用

pin.connect(pout);
的方式來建立兩者的連接。


除此之外,管道流提供了4個字段和1個方法:

protected static final int PIPE_SIZE
protected byte[] buffer
protected int in
protected int out
protected void receive(int b) throws IOException

in,out 是記錄位置的。


下面是一個例子:

寫線程寫入數據

import java.io.*;
public class FibonacciProducer extends Thread {
  private DataOutputStream theOutput;
  private int howMany;
  public FibonacciProducer(OutputStream out, int howMany) {
    theOutput = new DataOutputStream(out);
    this.howMany = howMany;
  }
  public void run( ) {
    try {
      int f1 = 1;
      int f2 = 1;
      theOutput.writeInt(f1);
      theOutput.writeInt(f2);
      // Now calculate the rest.
      for (int i = 2; i < howMany; i++) {
        int temp = f2;
        f2 = f2 + f1;
        f1 = temp;
        if (f2 < 0) { // overflow
         break;
        }
        theOutput.writeInt(f2);
      }
    }
    catch (IOException ex) { System.err.println(ex); }
  }
}
讀線程循環的讀出來
import java.io.*;
public class FibonacciConsumer extends Thread {
  private DataInputStream theInput;
  public FibonacciConsumer(InputStream in) {
    theInput = new DataInputStream(in);
  }
  public void run( ) {
    try {
      while (true) {
        System.out.println(theInput.readInt( ));
      }
    }
    catch (IOException ex) {
      if (ex.getMessage( ).equals("Pipe broken")) {
        // normal termination
        return;
      }
      System.err.println(ex);
    }
  }
}

有兩個地方會可能出現阻塞:

讀時爲空或者寫時爲滿


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章