Java InputStream to Byte Array dan ByteBuffer

1. Gambaran keseluruhan

Dalam tutorial ringkas ini, kita akan melihat cara mengubah InputStream menjadi byte [] dan ByteBuffer - pertama menggunakan Java biasa, kemudian menggunakan Guava dan Commons IO.

Artikel ini adalah sebahagian daripada siri "Java - Back to Basic" di Baeldung.

2. Tukar ke Array Byte

Mari kita lihat mendapatkan array bait dari aliran input sederhana . Aspek penting dari array bait adalah bahawa ia membolehkan akses (cepat) diindeks ke setiap nilai 8-bit (a bait) yang tersimpan dalam memori . Oleh itu, anda boleh memanipulasi bait ini untuk mengawal setiap bit. Kami akan melihat bagaimana cara menukar aliran input sederhana ke bait [] - pertama menggunakan Java biasa, kemudian menggunakan Guava dan Apache Commons IO.

2.1. Tukar Menggunakan Java Plain

Mari kita mulakan dengan penyelesaian Java yang difokuskan untuk menangani aliran ukuran tetap:

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

Sekiranya aliran buffered - di mana kita berhadapan dengan aliran buffered dan tidak mengetahui ukuran data yang tepat, kita perlu memastikan pelaksanaannya lebih fleksibel:

@Test public void givenUsingPlainJavaOnUnknownSizeStream_whenConvertingAnInputStreamToAByteArray_thenCorrect() throws IOException { InputStream is = new ByteArrayInputStream(new byte[] { 0, 1, 2 }); // not really unknown ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int nRead; byte[] data = new byte[1024]; while ((nRead = is.read(data, 0, data.length)) != -1) { buffer.write(data, 0, nRead); } buffer.flush(); byte[] byteArray = buffer.toByteArray(); }

Bermula dengan Java 9, kita dapat mencapai hal yang sama dengan kaedah khusus pada InputStream :

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

2.2. Tukarkan Menggunakan Jambu Batu

Sekarang mari kita lihat penyelesaian berasaskan Jambu Batu yang mudah - menggunakan kelas utiliti ByteStreams yang mudah:

@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. Tukar Menggunakan Commons IO

Dan akhirnya - penyelesaian mudah menggunakan Apache Commons IO:

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

Kaedah IOUtils.toByteArray () buffer input secara dalaman, jadi tidak perlu menggunakan instance BufferedInputStream ketika buffering diperlukan.

3. Tukar ke ByteBuffer

Sekarang, mari kita lihat mendapatkan ByteBuffer dari InputStream. Ini berguna setiap kali kita perlu melakukan operasi I / O peringkat rendah dengan cepat dan langsung dalam ingatan .

Dengan menggunakan pendekatan yang sama seperti bahagian di atas, kita akan melihat bagaimana mengubah InputStream menjadi ByteBuffer - pertama menggunakan Java biasa, kemudian menggunakan Guava dan Commons IO.

3.1. Tukar Menggunakan Java Plain

Sekiranya aliran bait - kami mengetahui ukuran data yang tepat. Mari gunakan kaedah yang tersedia ByteArrayInputStream # untuk membaca aliran bait ke dalam 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. Tukarkan Menggunakan Jambu Batu

Sekarang mari kita lihat penyelesaian berasaskan Jambu Batu yang mudah - menggunakan kelas utiliti ByteStreams yang mudah :

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

Di sini kita menggunakan loop sementara dengan kaedah hasRemaining untuk menunjukkan cara yang berbeza untuk membaca semua bait ke dalam ByteBuffer. Jika tidak, penegasan akan gagal kerana kedudukan indeks ByteBuffer akan menjadi sifar.

3.3. Tukar Menggunakan Commons IO

Dan akhirnya - menggunakan kelas Apache Commons IO dan 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. Kesimpulan

Artikel ini menggambarkan pelbagai cara untuk menukar aliran input mentah ke array byte dan ByteBuffer menggunakan Java, Guava, dan Apache Commons IO biasa.

Pelaksanaan semua contoh ini boleh didapati di projek GitHub kami.