1. Pengenalan
Kita sering perlu menukar antara array String dan bait di Java. Dalam tutorial ini, kita akan mengkaji operasi ini secara terperinci.
Pertama, kita akan melihat pelbagai cara untuk menukar String ke array byte . Kemudian, kita akan melihat operasi serupa secara terbalik.
2. Menukar String ke Array Byte
A String disimpan sebagai pelbagai watak Unikod di Jawa. Untuk menukarnya menjadi array byte , kami menerjemahkan urutan Karakter menjadi urutan bait. Untuk terjemahan ini, kami menggunakan contoh Charset . Kelas ini menentukan pemetaan antara urutan char dan urutan byte s .
Kami merujuk kepada proses di atas sebagai pengekodan .
Kita dapat mengekodkan String ke dalam array byte di Java dengan pelbagai cara. Mari lihat masing-masing secara terperinci dengan contoh.
2.1. Menggunakan String.getBytes ()
The String kelas menyediakan tiga beban getBytes kaedah untuk mengekod yang String ke dalam satu bait lokasi :
- getBytes () - mengekod menggunakan charset lalai platform
- getBytes (String charsetName) - mengekod menggunakan charset bernama
- getBytes (Charset charset) - mengekod menggunakan charset yang disediakan
Pertama, mari kita mengekod rentetan menggunakan charset lalai platform:
String inputString = "Hello World!"; byte[] byteArrray = inputString.getBytes();
Kaedah di atas bergantung pada platform kerana menggunakan charset lalai platform. Kita boleh mendapatkan charset ini dengan memanggil Charset.defaultCharset () .
Kedua, mari kita mengekodkan rentetan 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); }
Kaedah ini melontarkan UnsupportedEncodingException jika charset bernama tidak disokong.
Tingkah laku dua versi di atas tidak ditentukan sekiranya input mengandungi watak yang tidak disokong oleh charset. Sebaliknya, versi ketiga menggunakan array byte penggantian lalai charset untuk mengekod input yang tidak disokong.
Seterusnya, mari kita panggil versi ketiga kaedah getBytes () dan menyampaikan contoh 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 kaedah kilang Charset.forName untuk mendapatkan contoh Charset . Kaedah ini membuang pengecualian runtime jika nama charset yang diminta tidak sah. Ia juga membuang pengecualian runtime jika charset disokong dalam JVM semasa.
Namun, beberapa charset dijamin tersedia di setiap platform Java. The StandardCharsets kelas mentakrifkan pemalar untuk charset ini.
Akhirnya, mari kita mengekod menggunakan salah satu carta standard:
@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); }
Oleh itu, kami menyelesaikan kajian pelbagai versi getBytes . Seterusnya, mari kita lihat kaedah yang disediakan oleh Charset itu sendiri.
2.2. Menggunakan Charset.encode ()
The Set aksara kelas menyediakan mengekod () , kaedah yang mudah yang mengekod aksara Unicode ke dalam bait. Kaedah ini selalu menggantikan input yang tidak sah dan aksara yang tidak dapat digunakan menggunakan susunan bait pengganti lalai charset.
Mari gunakan kaedah encode untuk menukar 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 dapat kita lihat di atas, watak-watak yang tidak disokong telah diganti dengan bait pengganti lalai karet 63.
Pendekatan yang digunakan setakat ini menggunakan kelas CharsetEncoder secara dalaman untuk melakukan pengekodan. Mari kita periksa kelas ini di bahagian seterusnya.
2.3. CharsetEncoder
CharsetEncoder mengubah watak Unicode menjadi urutan bait untuk carset tertentu . Lebih-lebih lagi, ia memberikan kawalan terperinci terhadap proses pengekodan .
Mari gunakan kelas ini untuk menukar 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 contoh CharsetEncoder dengan memanggil kaedah newEncoder pada objek Charset .
Kemudian, kami menyatakan tindakan untuk keadaan ralat dengan menghubungi onMalformedInput () dan () onUnmappableCharacter kaedah . Kami dapat menentukan tindakan berikut:
- TAHNIAH - turunkan input yang salah
- GANTI - ganti input yang salah
- LAPORAN - laporkan ralat dengan mengembalikan objek CoderResult atau melemparkan CharacterCodingException
Selanjutnya, kami menggunakan kaedah substitWith () untuk menentukan susunan bait penggantian .
Oleh itu, kami menyelesaikan tinjauan pelbagai pendekatan untuk menukar String ke array byte. Mari kita lihat operasi terbalik.
3. Menukar Array Byte ke Rentetan
Kami merujuk kepada proses menukar array byte ke String sebagai penyahkodan . Sama seperti pengekodan, proses ini memerlukan Charset .
Walau bagaimanapun, kami tidak boleh menggunakan charset apa pun untuk menyahkod array bait. Kita harus menggunakan charset yang digunakan untuk mengekod String ke dalam array byte .
Kita boleh menukar array byte ke String dalam banyak cara. Mari kita periksa masing-masing secara terperinci.
3.1. Menggunakan String Constructor
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 penyahkodan secara dalaman menggunakan kelas CharsetDecoder . Kami boleh menggunakan kelas ini secara langsung untuk kawalan terperinci pada proses penyahkodan :
@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 input yang tidak sah dan watak yang tidak disokong dengan "?".
Sekiranya kami ingin dimaklumkan sekiranya terdapat input yang tidak sah, kami boleh menukar penyahkod sebagai:
decoder.onMalformedInput(CodingErrorAction.REPORT) .onUnmappableCharacter(CodingErrorAction.REPORT)
4. Kesimpulan
Dalam artikel ini, kami menyiasat pelbagai cara untuk menukar String ke array byte dan sebaliknya. Kita harus memilih kaedah yang sesuai berdasarkan data input dan juga tahap kawalan yang diperlukan untuk input yang tidak sah.
Seperti biasa, kod sumber lengkap boleh didapati di GitHub.