1. 概要

このクイックチュートリアルでは、InputStreambyte[]およびByteBufferに変換する方法を見ていきます–最初にプレーンJavaを使用します]、次にGuavaとCommonsIOを使用します。

この記事は、ここBaeldungの「Java –BacktoBasic」シリーズの一部です。

2. バイト配列に変換

単純な入力ストリームからバイト配列を取得する方法を見てみましょう。 。 バイト配列の重要な側面は、 これにより、メモリに格納されている各8ビット(バイト)値へのインデックス付き(高速)アクセスが可能になります 。 したがって、これらのバイトを操作して各ビットを制御できます。 単純な入力ストリームをbyte[] に変換する方法を見ていきます。最初にプレーンJavaを使用し、次にGuavaApacheCommonsIOを使用します。 ]。

2.1. プレーンJavaを使用して変換する

固定サイズのストリームの処理に焦点を当てたJavaソリューションから始めましょう。

@Test
public void givenUsingPlainJavaOnFixedSizeStream_whenConvertingAnInputStreamToAByteArray_thenCorrect() 
  throws IOException {
    InputStream is = new ByteArrayInputStream(new byte[] { 0, 1, 2 });
    byte[] targetArray = new byte[is.available()];

    is.read(targetArray);
}

バッファリングされたストリームの場合–バッファリングされたストリームを処理していて、基になるデータの正確なサイズがわからない場合は、実装をより柔軟にする必要があります。

@Test
public void givenUsingPlainJavaOnUnknownSizeStream_whenConvertingAnInputStreamToAByteArray_thenCorrect() 
  throws IOException {
    InputStream is = new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4, 5, 6 }); // not really known
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();

    int nRead;
    byte[] data = new byte[4];

    while ((nRead = is.read(data, 0, data.length)) != -1) {
        buffer.write(data, 0, nRead);
    }

    buffer.flush();
    byte[] targetArray = buffer.toByteArray();
}

Java 9以降、専用のreadNbytesメソッドを使用して同じことを実現できます。

@Test
public void givenUsingPlainJava9OnUnknownSizeStream_whenConvertingAnInputStreamToAByteArray_thenCorrect() 
  throws IOException {
    InputStream is = new ByteArrayInputStream(new byte[] { 0, 1, 2, 3, 4, 5, 6 });
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();

    int nRead;
    byte[] data = new byte[4];

    while ((nRead = is.readNBytes(data, 0, data.length)) != 0) {
        System.out.println("here " + nRead);
        buffer.write(data, 0, nRead);
    }

    buffer.flush();
    byte[] targetArray = buffer.toByteArray();
}

これら2つの方法の違いは非常に微妙です。

最初のread(byte [] b、int off、int len)は、入力ストリームから最大lenバイトのデータを読み取りますが、2番目の readNBytes(byte [ ] b、int off、int len)は、要求されたバイト数を正確に読み取ります。

さらに、入力ストリームに使用可能なデータがない場合、read-1を返します。 ただし、 readNbytes は、常にバッファに読み込まれた実際のバイト数を返します。

すべてのバイトを一度に読み取ることもできます。

@Test
public void
  givenUsingPlainJava9_whenConvertingAnInputStreamToAByteArray_thenCorrect()
  throws IOException {
    InputStream is = new ByteArrayInputStream(new byte[] { 0, 1, 2 });

    byte[] data = is.readAllBytes();
}

2.2. Guavaを使用して変換する

次に、便利なByteStreamsユーティリティクラスを使用した、単純なGuavaベースのソリューションを見てみましょう。

@Test
public void givenUsingGuava_whenConvertingAnInputStreamToAByteArray_thenCorrect() 
  throws IOException {
    InputStream initialStream = ByteSource.wrap(new byte[] { 0, 1, 2 }).openStream();
    
    byte[] targetArray = ByteStreams.toByteArray(initialStream);
}

2.3. CommonsIOを使用して変換する

そして最後に– Apache CommonsIOを使用した簡単なソリューション:

@Test
public void givenUsingCommonsIO_whenConvertingAnInputStreamToAByteArray_thenCorrect() 
  throws IOException {
    ByteArrayInputStream initialStream = new ByteArrayInputStream(new byte[] { 0, 1, 2 });
    
    byte[] targetArray = IOUtils.toByteArray(initialStream);
}

メソッドIOUtils.toByteArray()は入力を内部でバッファリングするため、バッファリングが必要な場合はBufferedInputStreamインスタンスを使用する必要はありません。

3. ByteBufferに変換します

それでは、 ByteBuffer から InputStream。 これはメモリ内で高速かつ直接的な低レベルのI/O操作を実行する必要がある場合に役立ちます

上記のセクションと同じアプローチを使用して、InputStreamByteBufferに変換する方法を見ていきます。最初にプレーンJavaを使用し、次にGuavaとCommonsIOを使用します。 。

3.1. プレーンJavaを使用して変換する

バイトストリームの場合–基になるデータの正確なサイズがわかります。 ByteArrayInputStream#available メソッドを使用して、バイトストリームをByteBufferに読み込みます。

@Test
public void givenUsingCoreClasses_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() 
  throws IOException {
    byte[] input = new byte[] { 0, 1, 2 };
    InputStream initialStream = new ByteArrayInputStream(input);
    ByteBuffer byteBuffer = ByteBuffer.allocate(3);
    while (initialStream.available() > 0) {
        byteBuffer.put((byte) initialStream.read());
    }

    assertEquals(byteBuffer.position(), input.length);
}

3.2. Guavaを使用して変換する

次に、便利なByteStreamsユーティリティクラスを使用した単純なGuavaベースのソリューションを見てみましょう。

@Test
public void givenUsingGuava__whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() 
  throws IOException {
    InputStream initialStream = ByteSource
      .wrap(new byte[] { 0, 1, 2 })
      .openStream();
    byte[] targetArray = ByteStreams.toByteArray(initialStream);
    ByteBuffer bufferByte = ByteBuffer.wrap(targetArray);
    while (bufferByte.hasRemaining()) {
        bufferByte.get();
    }

    assertEquals(bufferByte.position(), targetArray.length);
}

ここでは、メソッド hasRemaining でwhileループを使用して、すべてのバイトを ByteBufferに読み込む別の方法を示します。そうでない場合、 ByteBuffer [X201X ]インデックス位置はゼロになります。

3.3. CommonsIOを使用して変換する

そして最後に– ApacheCommonsIOとIOUtilsクラスを使用します。

@Test
public void givenUsingCommonsIo_whenByteArrayInputStreamToAByteBuffer_thenLengthMustMatch() 
  throws IOException {
    byte[] input = new byte[] { 0, 1, 2 };
    InputStream initialStream = new ByteArrayInputStream(input);
    ByteBuffer byteBuffer = ByteBuffer.allocate(3);
    ReadableByteChannel channel = newChannel(initialStream);
    IOUtils.readFully(channel, byteBuffer);

    assertEquals(byteBuffer.position(), input.length);
}

4. 結論

この記事では、プレーンJava、Guava、およびApache Commons IOを使用して、生の入力ストリームをバイト配列とByteBufferに変換するさまざまな方法について説明しました。

これらすべての例の実装は、GitHubプロジェクトにあります。