Ubah String menjadi Byte Array dan Reverse di Java

1. Perkenalan

Kita sering perlu mengkonversi antara String dan byte array di Java. Dalam tutorial ini, kami akan memeriksa operasi ini secara detail.

Pertama, kita akan melihat berbagai cara untuk mengubah String menjadi array byte . Kemudian, kita akan melihat operasi serupa secara terbalik.

2. Mengubah String menjadi Byte Array

Sebuah String disimpan sebagai array dari karakter Unicode di Jawa. Untuk mengubahnya menjadi array byte , kami menerjemahkan urutan Karakter menjadi urutan byte. Untuk terjemahan ini, kami menggunakan instance Charset . Kelas ini menentukan pemetaan antara urutan arang dan urutan byte s .

Kami menyebut proses di atas sebagai pengkodean .

Kita dapat menyandikan String ke dalam array byte di Java dengan berbagai cara. Mari kita lihat masing-masing secara detail dengan contoh.

2.1. Menggunakan String.getBytes ()

Kelas String menyediakan tiga metode getBytes yang kelebihan beban untuk mengenkode String ke dalam array byte :

  • getBytes () - menyandikan menggunakan rangkaian karakter default platform
  • getBytes (String charsetName) - menyandikan menggunakan charset bernama
  • getBytes (Charset charset) - mengkodekan menggunakan charset yang disediakan

Pertama, mari kita mengenkode string menggunakan charset default platform:

String inputString = "Hello World!"; byte[] byteArrray = inputString.getBytes();

Metode di atas bergantung pada platform karena menggunakan charset default platform. Kita bisa mendapatkan charset ini dengan memanggil Charset.defaultCharset () .

Kedua, mari kita menyandikan string menggunakan charset bernama:

@Test public void whenGetBytesWithNamedCharset_thenOK() throws UnsupportedEncodingException { String inputString = "Hello World!"; String charsetName = "IBM01140"; byte[] byteArrray = inputString.getBytes("IBM01140"); assertArrayEquals( new byte[] { -56, -123, -109, -109, -106, 64, -26, -106, -103, -109, -124, 90 }, byteArrray); }

Metode ini menampilkan UnsupportedEncodingException jika charset bernama tidak didukung.

Perilaku dari dua versi di atas tidak ditentukan jika input berisi karakter yang tidak didukung oleh charset. Sebaliknya, versi ketiga menggunakan array byte pengganti default charset untuk mengenkode input yang tidak didukung.

Selanjutnya, mari panggil versi ketiga dari metode getBytes () dan berikan instance Charset:

@Test public void whenGetBytesWithCharset_thenOK() { String inputString = "Hello ਸੰਸਾਰ!"; Charset charset = Charset.forName("ASCII"); byte[] byteArrray = inputString.getBytes(charset); assertArrayEquals( new byte[] { 72, 101, 108, 108, 111, 32, 63, 63, 63, 63, 63, 33 }, byteArrray); }

Di sini, kami menggunakan metode pabrik Charset.forName untuk mendapatkan instance Charset . Metode ini menampilkan pengecualian waktu proses jika nama rangkaian karakter yang diminta tidak valid. Ini juga melontarkan pengecualian waktu proses jika rangkaian karakter didukung di JVM saat ini.

Namun, beberapa charset dijamin tersedia di setiap platform Java. Kelas StandardCharsets menentukan konstanta untuk rangkaian karakter ini.

Terakhir, mari kita encode menggunakan salah satu rangkaian karakter standar:

@Test public void whenGetBytesWithStandardCharset_thenOK() { String inputString = "Hello World!"; Charset charset = StandardCharsets.UTF_16; byte[] byteArrray = inputString.getBytes(charset); assertArrayEquals( new byte[] { -2, -1, 0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0, 100, 0, 33 }, byteArrray); }

Dengan demikian, kami menyelesaikan review dari berbagai versi getBytes . Selanjutnya, mari kita lihat metode yang disediakan oleh Charset itu sendiri.

2.2. Menggunakan Charset.encode ()

Kelas Charset menyediakan encode () , metode praktis yang mengkodekan karakter Unicode menjadi byte. Metode ini selalu menggantikan input yang tidak valid dan karakter yang tidak dapat dipetakan menggunakan array byte pengganti default dari charset.

Mari gunakan metode encode untuk mengubah String menjadi array byte :

@Test public void whenEncodeWithCharset_thenOK() { String inputString = "Hello ਸੰਸਾਰ!"; Charset charset = StandardCharsets.US_ASCII; byte[] byteArrray = charset.encode(inputString).array(); assertArrayEquals( new byte[] { 72, 101, 108, 108, 111, 32, 63, 63, 63, 63, 63, 33 }, byteArrray); }

Seperti yang kita lihat di atas, karakter yang tidak didukung telah diganti dengan byte pengganti default charset 63.

Pendekatan yang digunakan sejauh ini menggunakan kelas CharsetEncoder secara internal untuk melakukan pengkodean. Mari kita periksa kelas ini di bagian selanjutnya.

2.3. CharsetEncoder

CharsetEncoder mengubah karakter Unicode menjadi urutan byte untuk charset tertentu . Selain itu, ini memberikan kontrol yang sangat baik atas proses encoding .

Mari gunakan kelas ini untuk mengubah String menjadi array byte :

@Test public void whenUsingCharsetEncoder_thenOK() throws CharacterCodingException { String inputString = "Hello ਸੰਸਾਰ!"; CharsetEncoder encoder = StandardCharsets.US_ASCII.newEncoder(); encoder.onMalformedInput(CodingErrorAction.IGNORE) .onUnmappableCharacter(CodingErrorAction.REPLACE) .replaceWith(new byte[] { 0 }); byte[] byteArrray = encoder.encode(CharBuffer.wrap(inputString)) .array(); assertArrayEquals( new byte[] { 72, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 33 }, byteArrray); }

Di sini, kami membuat instance CharsetEncoder dengan memanggil metode newEncoder pada objek Charset .

Kemudian, kita menentukan tindakan untuk kondisi kesalahan dengan menelepon onMalformedInput () dan () onUnmappableCharacter metode . Kami dapat menentukan tindakan berikut:

  • ABAIKAN - hilangkan input yang salah
  • REPLACE - ganti input yang salah
  • LAPORAN - laporkan kesalahan dengan mengembalikan objek CoderResult atau melempar CharacterCodingException

Selanjutnya, kami menggunakan metode replaceWith () untuk menentukan array byte pengganti .

Jadi, kami menyelesaikan tinjauan berbagai pendekatan untuk mengubah String menjadi array byte. Selanjutnya mari kita lihat operasi kebalikannya.

3. Mengubah Byte Array menjadi String

Kami mengacu pada proses mengubah array byte menjadi String sebagai decoding . Mirip dengan encoding, proses ini membutuhkan Charset .

Namun, kita tidak bisa begitu saja menggunakan charset apa pun untuk mendekode array byte. Kita harus menggunakan charset yang digunakan untuk menyandikan String ke dalam array byte .

Kita dapat mengonversi array byte menjadi String dengan banyak cara. Mari kita periksa masing-masing secara rinci.

3.1. Menggunakan Konstruktor String

The String class has few constructors which take a byte array as input. They are all similar to the getBytes method but work in reverse.

First, let's convert a byte array to String using the platform's default charset:

@Test public void whenStringConstructorWithDefaultCharset_thenOK() { byte[] byteArrray = { 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33 }; String string = new String(byteArrray); assertNotNull(string); }

Note that we don't assert anything here about the contents of the decoded string. This is because it may decode to something different, depending on the platform's default charset.

For this reason, we should generally avoid this method.

Secondly, let's use a named charset for decoding:

@Test public void whenStringConstructorWithNamedCharset_thenOK() throws UnsupportedEncodingException { String charsetName = "IBM01140"; byte[] byteArrray = { -56, -123, -109, -109, -106, 64, -26, -106, -103, -109, -124, 90 }; String string = new String(byteArrray, charsetName); assertEquals("Hello World!", string); }

This method throws an exception if the named charset is not available on the JVM.

Thirdly, let's use a Charset object to do decoding:

@Test public void whenStringConstructorWithCharSet_thenOK() { Charset charset = Charset.forName("UTF-8"); byte[] byteArrray = { 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33 }; String string = new String(byteArrray, charset); assertEquals("Hello World!", string); }

Finally, let's use a standard Charset for the same:

@Test public void whenStringConstructorWithStandardCharSet_thenOK() { Charset charset = StandardCharsets.UTF_16; byte[] byteArrray = { -2, -1, 0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0, 100, 0, 33 }; String string = new String(byteArrray, charset); assertEquals("Hello World!", string); }

So far, we have converted a byte array into a String using the constructor. Let's now look into the other approaches.

3.2. Using Charset.decode()

The Charset class provides the decode() method that converts a ByteBuffer to String:

@Test public void whenDecodeWithCharset_thenOK() { byte[] byteArrray = { 72, 101, 108, 108, 111, 32, -10, 111, 114, 108, -63, 33 }; Charset charset = StandardCharsets.US_ASCII; String string = charset.decode(ByteBuffer.wrap(byteArrray)) .toString(); assertEquals("Hello �orl�!", string); }

Here, the invalid input is replaced with the default replacement character for the charset.

3.3. CharsetDecoder

Semua pendekatan sebelumnya untuk mendekode secara internal menggunakan kelas CharsetDecoder . Kita dapat menggunakan kelas ini secara langsung untuk kontrol mendetail pada proses decoding :

@Test public void whenUsingCharsetDecoder_thenOK() throws CharacterCodingException { byte[] byteArrray = { 72, 101, 108, 108, 111, 32, -10, 111, 114, 108, -63, 33 }; CharsetDecoder decoder = StandardCharsets.US_ASCII.newDecoder(); decoder.onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) .replaceWith("?"); String string = decoder.decode(ByteBuffer.wrap(byteArrray)) .toString(); assertEquals("Hello ?orl?!", string); }

Di sini, kami mengganti masukan yang tidak valid dan karakter yang tidak didukung dengan "?".

Jika kami ingin diberi tahu jika ada input yang tidak valid, kami dapat mengubah decoder sebagai:

decoder.onMalformedInput(CodingErrorAction.REPORT) .onUnmappableCharacter(CodingErrorAction.REPORT)

4. Kesimpulan

Pada artikel ini, kami menyelidiki berbagai cara untuk mengubah String menjadi array byte dan sebaliknya. Kita harus memilih metode yang sesuai berdasarkan data masukan serta tingkat kontrol yang diperlukan untuk masukan yang tidak valid.

Seperti biasa, kode sumber lengkap dapat ditemukan di GitHub.