将Java字节读取器转换为InputStream

将Java字节读取器转换为InputStream,java,byte,bytearray,inputstream,Java,Byte,Bytearray,Inputstream,考虑一个通用的字节读取器实现以下简单API,以从无法访问的数据结构中读取未指定数量的字节: public interface ByteReader { public byte[] read() throws IOException; // Returns null only at EOF } 如何将上述内容有效地转换为标准,以便使用InputStream类定义的所有方法的应用程序按预期工作 一个简单的解决方案是将InputStream子类化为 根据InputStream的read(…)

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

public interface ByteReader
{
    public byte[] read() throws IOException; // Returns null only at EOF
}
如何将上述内容有效地转换为标准,以便使用
InputStream
类定义的所有方法的应用程序按预期工作

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

  • 根据
    InputStream的
    read(…)
    方法的需要,调用
    ByteReader的
    read()
    方法
  • 缓冲在字节[]数组中检索的字节
  • 按预期返回字节数组的一部分,例如,每当调用
    InputStream read()
    方法时,每次返回一个字节
  • 然而,这需要更多的工作来提高效率(例如,避免多字节数组分配)。此外,对于要扩展到大输入大小的应用程序,将所有内容读入内存然后进行处理不是一个选项

    有什么想法或开源实现可以使用吗?

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

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

    看来你可能正在冒着在这里重新发明轮子的风险。如果可能的话,我会考虑完全删除您的<代码> ByteReader < /C>接口,而使用以下选项之一:

  • 替换为
    ByteInputStream
  • 使用其他各种
    InputStream
    类(取决于数据源)
  • 使用自定义实现扩展
    InputStream
  • 我会坚持使用现有的
    InputStream
    类。我不知道您的代码是如何构造的,但是您可以,例如,向您当前的数据源添加一个
    getInputStream()
    方法,并让它们返回一个适当的已经存在的
    InputStream
    (或自定义子类,如果需要)


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

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

    诀窍是实现一个
    枚举
    ,它可以使用
    ByTerReader

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


    final Enumeration basEnum=新枚举(){
    Bytearrayinputs;
    布尔结束;
    @凌驾
    公共布尔值hasMoreElements(){
    若果(完){
    返回false;
    }
    if(baos==null){
    getNextBA();
    若果(完){
    返回false;
    }
    }
    返回true;
    }
    @凌驾
    public ByteArrayInputStream nextElement(){
    若果(完){
    抛出新的NoTouchElementException();
    }
    如果(baos.available()!=0){
    返回宝;
    }
    getNextBA();
    返回宝;
    }
    私有void getNextBA(){
    字节[]下一个;
    试一试{
    next=byteReader.read();
    }捕获(IOE异常){
    抛出新的IllegalStateException(“读取字节数组的问题”);
    }
    if(next==null){
    结束=真;
    返回;
    }
    this.baos=新的ByteArrayInputStream(下一个);
    }
    };
    SequenceInputStream sis=新SequenceInputStream(basEnum);
    
    检查了源代码。我认为它使用了类似的想法,也许你可以扩展它,从你的数据结构中读取是的,我在写问题之前已经检查过了。本质上需要一个类似fill()的函数,但在ByteArrayInputStream实现中它似乎太复杂了,所以我想知道是否有更简单的方法。@PNS您可以使用
    Arrays.fill()
    ByteInputStream的基础数组上。这仅适用于将一个值设置为多个数组位置。:-)不,你不能,但那不是问题的主题。在检查效率之前,必须先将ByterReader转换为InputStream。我知道SequenceInputStream,但使用ByteArrayInputStream既不高效,也不同步。仅当检索和缓冲的字节不足以满足InputStream read(…)方法的要求时,才需要调用ByteReader read()方法。
    new BufferedInputStream(new ByteArrayInputStream(…)
    不够吗?不,请参阅我对答案的评论。感谢和+1的实现,但这是没有效率的。想象一下,在一个大文件上必须调用ByteReader.read()数千次或数百万次……什么意思,效率不高?您为我们提供了一个我使用的单一接口。它不会创建任何额外的缓冲区。它唯一创建的是附加对象,这些对象很小,可以很容易地进行垃圾收集。您向我们寻求帮助,但您认为您有足够的知识立即判断任何提交。您的字节数据最初来自哪里?
    new BufferedInputStream(new ByteArrayInputStream(…)
    不够吗?在我的用例中没有原始数据访问,因此描述了ByteReader接口。了解dat的位置会很有帮助
    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);