将Java字节读取器转换为InputStream

时间:2013-08-12 18:41:33

标签: java byte bytearray inputstream

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

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

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

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

  1. 根据read()
  2. ByteReader方法,根据需要调用read(...) InputStream方法
  3. 缓冲在byte [] array
  4. 中检索到的字节
  5. 按预期返回字节数组的一部分,例如,每当调用InputStream read()方法时,一次返回1个字节。
  6. 然而,这需要更多工作才能有效(例如,为了避免多字节阵列分配)。此外,对于扩展到大输入大小的应用程序,将所有内容读入内存然后处理不是一种选择。

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

2 个答案:

答案 0 :(得分:1)

我认为,通过使用“转换”,替换是可以接受的。

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

看起来你可能冒着重新发明轮子的风险。如果可能,我会考虑完全取消您的InputStream界面,而是选择其中一个选项:

  1. 替换为ByteReader
  2. 使用各种其他ByteInputStream类(取决于数据来源)。
  3. 使用您的自定义实现扩展InputStream
  4. 我到处都坚持现有的InputStream课程。我不知道你的代码是如何构造的,但是你可以,例如,为你当前的数据源添加一个InputStream方法,并让它们返回一个适当的已存在getInputStream()(或者自定义子类,如果必要)。

    顺便提一下,我建议在您自己的IO类中避免使用术语InputStream,因为{SDK}已经在Java SDK中大量使用Reader来指示对编码字符数据进行操作的流读取器(相反)通常对原始字节数据进行操作的Reader

答案 1 :(得分: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);