將 Java 字節讀取器轉換為 InputStream (Converting a Java byte reader to an InputStream)


問題描述

將 Java 字節讀取器轉換為 InputStream (Converting a Java byte reader to an InputStream)

Consider a generic byte reader implementing the following simple API to read an unspecified number of bytes from a data structure that is otherwise inaccessible:

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

How could the above be efficiently converted to a standard Java InputStream, so that an application using all methods defined by the InputStream class, works as expected?

A simple solution would be subclassing InputStream to

  1. Call the read() method of the ByteReader as much as needed by the read(...) methods of the InputStream
  2. Buffer the bytes retrieved in a byte[] array
  3. Return part of the byte array as expected, e.g., 1 byte at a time whenever the InputStream read() method is called.

However, this requires more work to be efficient (e.g., for avoiding multiple byte array allocations). Also, for the application to scale to large input sizes, reading everything into memory and then processing is not an option.

Any ideas or open source implementations that could be used?


參考解法

方法 1:

I assume, by your use of "convert", that a replacement is acceptable.

The easiest way to do this is to just use a ByteArrayInputStream, which already provides all the features you are looking for (but must wrap an existing array), or to use any of the other already provided InputStream for reading data from various sources.

It seems like you may be running the risk of reinventing wheels here. If possible, I would consider scrapping your ByteReader interface entirely, and instead going with one of these options:

  1. Replace with ByteInputStream.
  2. Use the various other InputStream classes (depending on the source of the data).
  3. Extend InputStream with your custom implementation.

I'd stick to the existing InputStream class everywhere. I have no idea how your code is structured but you could, for example, add a getInputStream() method to your current data sources, and have them return an appropriate already‑existing InputStream (or a custom subclass if necessary).

By the way, I recommend avoiding the term Reader in your own IO classes, as Reader is already heavily used in the Java SDK to indicate stream readers that operate on encoded character data (as opposed to InputStream which generally operates on raw byte data).

方法 2:

Create multiple ByteArrayInputStream instances around the returned arrays and use them in a stream that provides for concatenation. You could for instance use SequenceInputStream for this.

Trick is to implement a Enumeration<ByteArrayInputStream> that is can use the ByteReader class.

EDIT: I've implemented this answer, but it is probably better to create your own InputStream instance instead. Unfortunately, this solution does not let you handle IOException gracefully.


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);

(by PNSJason CMaarten Bodewes)

參考文件

  1. Converting a Java byte reader to an InputStream (CC BY‑SA 3.0/4.0)

#bytearray #java #inputstream #byte






相關問題

更改創建 XML 閱讀器時使用的 XmlDictionaryReaderQuotas 對象的 MaxArrayLength 屬性 (Changing the MaxArrayLength property on the XmlDictionaryReaderQuotas object used when creating the XML reader)

將文件讀入 4 個字節的 ByteArrays (Read file into ByteArrays of 4 bytes)

使用套接字 (C#) 進行文件傳輸 - 接收到的文件不包含完整數據 (File transfer using sockets (C#) - received file doesn't contain full data)

將 Java 字節讀取器轉換為 InputStream (Converting a Java byte reader to an InputStream)

用 bigInteger 和其他方法重建字節數組 (Rebuild byte array with bigInteger and other method)

如何將字節數組作為參數發送到 HTML.Action? (How to send byte array as paramater to HTML.Action?)

如何將存儲在字節數組中的圖像加載到 WebView? (How to load an image stored in a byte array to WebView?)

我希望將畫布保存為 mySql blob 字段中的 blob (I am looking to save a canvas as a blob in mySql blob field)

將字節數組的部分轉換為整數值 (Converting sections of byte arrays to integer values)

從內存中釋放 jni 引用 (Freeing jni references from memory)

為什麼 JPGEncoded bytearray 從 AS3 發送到 AMFPHP 會導致圖像無效? (Why is JPGEncoded bytearray sent from AS3 to AMFPHP resulting in an invalid image?)

Java:字節到浮點數/整數 (Java: Bytes to floats / ints)







留言討論