如何使用序列输入流?

How to use SequenceInputStream?

背景

代码

package book1.chapter10;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.SequenceInputStream;

public class Test1 {
    public static void main(String[] args) throws IOException {
        byte[] box = new byte[50];
        FileInputStream fin1 = new FileInputStream("D:/Workspace/Java/src/book1/chapter10/data1.txt");
        FileInputStream fin2 = new FileInputStream("D:/Workspace/Java/src/book1/chapter10/data2.txt");
        //fin1's content:"learn!".
        //fin2's content:"java!".
        SequenceInputStream finAll = new SequenceInputStream(fin1,fin2);
        System.out.println("available:" + finAll.available());
        //try read ten:
        finAll.read(box,0,10);
        System.out.println("available:" + finAll.available());
        //try read one more:
        int temp = fin1.read();
        System.out.println("available:" + finAll.available());
        //outcome:
        for(byte x: box) {
            if (x != 0) System.out.print(x +",");
        }
        System.out.println(temp == -1);
        //try read ten again!
        byte[] newBox = new byte[50];
        finAll.read(newBox,0,10);
        System.out.println("available:" + finAll.available());
        //outcome:
        for(byte x: newBox) {
            if (x != 0) System.out.print(x +",");
        }
    }
}

结果

available:6
available:0
available:0
108,101,97,114,110,33,true
available:0
106,97,118,97,33,

问题

如 javadoc 中所述:

Reads up to len bytes of data from this input stream into an array of bytes. If len is not zero, the method blocks until at least 1 byte of input is available; otherwise, no bytes are read and 0 is returned. The read method of SequenceInputStream tries to read the data from the current substream. If it fails to read any characters because the substream has reached the end of the stream, it calls the close method of the current substream and begins reading from the next substream.

所以只读取从当前子流到 EOF 的 return 个字符。之后需要重新读取。

例如:

public static void main(String[] args) throws IOException {
    InputStream in1 = new ByteArrayInputStream("Foo".getBytes());
    InputStream in2 = new ByteArrayInputStream("Barbar".getBytes());
    SequenceInputStream seq = new SequenceInputStream(in1, in2);
    read(seq);
    read(seq);
    read(seq);
    System.out.println("avail " + seq.available());
}

private static void read(SequenceInputStream seq) throws IOException {
    byte[] buffer = new byte[50];
    System.out.println("avail " + seq.available() + " read " + seq.read(buffer, 0, 5) + " ");
    System.out.println(new String(buffer));
}

结果:

avail 3 read 3 
Foo
avail 0 read 5 
Barba
avail 1 read 1 
r
avail 0

为什么方法(读取)遇到EOF就停止了?

您可能希望它在第一次调用 read 时显示为“learn!java”,但这不是 read 记录要做的(强调我的):

The read method of SequenceInputStream tries to read the data from the current substream. If it fails to read any characters because the substream has reached the end of the stream, it calls the close method of the current substream and begins reading from the next substream.

“当前子流”是此处的关键字。它不会尝试从任何其他子流读取数据,而是 current 一个。在您创建 SequenceInputStream 之后,当前子流是第一个 - fin1。因此,对 read 的第一次调用将从 fin1 读取,而您不会从 fin2.

获得任何信息

无参数read也说了类似的话。

This method tries to read one character from the current substream. If it reaches the end of the stream, it calls the close method of the current substream and begins reading from the next substream.

如何阅读下一个流?

嗯,根据每个引用的后半部分,当 SequenceInputStream 无法再从当前流中读取任何内容时,它会从下一个流中读取。在您的代码中,对 finAll.read 的第一次调用读取了 fin1 中的所有内容,因此第二次调用无法再从 fin1 中读取任何内容,因此它从 fin2 开始读取。

如果希望读取的数据在同一个字节数组中,只需将offset参数改为读取的字节数即可:

int bytesRead = finAll.read(box, 0, 10);
finAll.read(box, bytesRead, 10 - bytesRead);