-2

考虑一个实现以下简单 API 的通用字节读取器,以从无法访问的数据结构中读取未指定数量的字节:

public interface ByteReader
{
    public byte[] read() throws IOException; // Returns null only at EOF
}

如何将上述内容有效地转换为标准Java InputStream,以便使用InputStream该类定义的所有方法的应用程序按预期工作?

一个简单的解决方案是将子类InputStream化为

  1. 尽可能多地调用的read()方法ByteReaderread(...)InputStream
  2. 缓冲在 byte[] 数组中检索到的字节
  3. 按预期返回字节数组的一部分,例如,每当InputStream read()调用该方法时一次返回 1 个字节。

然而,这需要更多的工作来提高效率(例如,为了避免多字节数组分配)。此外,为了使应用程序扩展到较大的输入大小,将所有内容读入内存然后进行处理不是一种选择。

任何可以使用的想法或开源实现?

4

2 回答 2

1

我假设,通过您使用“转换”,替换是可以接受的。

最简单的方法是只使用 a ByteArrayInputStream,它已经提供了您正在寻找的所有功能(但必须包装现有数组),或者使用已经提供的任何其他功能InputStream来从各种来源读取数据。

看起来你可能在这里冒着重新发明轮子的风险。如果可能的话,我会考虑ByteReader完全废弃您的界面,而是使用以下选项之一:

  1. 替换为ByteInputStream
  2. 使用各种其他InputStream类(取决于数据源)。
  3. InputStream使用您的自定义实现进行扩展。

我会在任何地方坚持现有的InputStream课程。我不知道您的代码是如何构造的,但是您可以,例如,getInputStream()向您当前的数据源添加一个方法,并让它们返回一个适当的已经存在的InputStream(或者如果需要,一个自定义子类)。

顺便说一句,我建议Reader在您自己的 IO 类中避免使用该术语,因为Reader它已经在 J​​ava SDK 中大量用于指示对编码字符数据进行操作的流读取器(而不是InputStream通常对原始字节数据进行操作)。

于 2013-08-12T18:47:18.617 回答
1

围绕返回的数组创建多个ByteArrayInputStream实例,并在提供连接的流中使用它们。例如,您可以为此使用SequenceInputStream

诀窍是实现一个Enumeration<ByteArrayInputStream>可以使用的ByteReader类。

编辑:我已经实现了这个答案,但最好创建自己的InputStream实例。不幸的是,这个解决方案不能让你IOException优雅地处理。


final Enumeration<ByteArrayInputStream> basEnum = new Enumeration<ByteArrayInputStream>() {

    ByteArrayInputStream baos;
    boolean ended;

    @Override
    public boolean hasMoreElements() {
        if (ended) {
            return false;
        }

        if (baos == null) {
            getNextBA();
            if (ended) {
                return false;
            }
        }

        return true;
    }

    @Override
    public ByteArrayInputStream nextElement() {
        if (ended) {
            throw new NoSuchElementException();
        }
        if (baos.available() != 0) {
            return baos;
        }

        getNextBA();
        return baos;
    }

    private void getNextBA() {

        byte[] next;
        try {
            next = byteReader.read();
        } catch (IOException e) {
            throw new IllegalStateException("Issues reading byte arrays");
        }
        if (next == null) {
            ended = true;
            return;
        }
        this.baos = new ByteArrayInputStream(next);
    }
};

SequenceInputStream sis = new SequenceInputStream(basEnum);
于 2013-08-12T18:47:52.657 回答