Encode a String to UTF-8 trong Java

Encode a String to UTF-8 trong Java

Encode a String to UTF-8 trong Java

Giới thiệu Khi làm việc với Chuỗi trong Java , đôi khi chúng ta cần mã hóa chúng thành một bộ ký tự cụ thể, chẳng hạn như UTF-8. UTF-8 đại d...
Comment tháng 6 21, 2021

Giới thiệu

Khi làm việc với Chuỗi trong Java, đôi khi chúng ta cần mã hóa chúng thành một bộ ký tự cụ thể, chẳng hạn như UTF-8.
UTF-8 đại diện cho một mã hóa ký tự có độ rộng thay đổi sử dụng từ một đến bốn byte tám bit để đại diện cho tất cả các điểm mã Unicode hợp lệ.
Một điểm mã có thể đại diện cho các ký tự đơn lẻ, nhưng cũng có các ý nghĩa khác, chẳng hạn như để định dạng. "Độ rộng có thể thay đổi" có nghĩa là nó mã hóa mỗi điểm mã với một số byte khác nhau (từ một đến bốn) và như một biện pháp tiết kiệm không gian, các điểm mã thường được sử dụng được biểu thị bằng ít byte hơn so với các điểm mã được sử dụng ít thường xuyên hơn.


UTF-8 sử dụng một byte để biểu diễn các điểm mã từ 0-127, làm cho 128 điểm mã đầu tiên trở thành bản đồ 1-1 với các ký tự ASCII, vì vậy UTF-8 tương thích ngược với ASCII.

Lưu ý: Java mã hóa tất cả các Chuỗi thành UTF-16, sử dụng tối thiểu hai byte để lưu trữ các điểm mã. Tại sao chúng ta cần chuyển đổi sang UTF-8 sau đó?
Không phải tất cả đầu vào đều có thể là UTF-16 hoặc UTF-8 cho vấn đề đó. Bạn có thể thực sự nhận được một Chuỗi được mã hóa ASCII, không hỗ trợ nhiều ký tự như UTF-8. Ngoài ra, không phải tất cả đầu ra đều có thể xử lý UTF-16, vì vậy việc chuyển đổi sang UTF-8 phổ biến hơn là điều hợp lý.
Chúng tôi sẽ làm việc với một số Chuỗi chứa các ký tự Unicode mà bạn có thể không gặp hàng ngày - chẳng hạn như č, ß và あ, mô phỏng hành động nhập của người dùng.

String serbianString = "Šta radiš?"; // What are you doing?
String germanString = "Wie heißen Sie?"; // What's your name?
String japaneseString = "よろしくお願いします"; // Pleased to meet you

Bây giờ, hãy tận dụng phương thức khởi tạo Chuỗi (byte [] byte, bảng mã Charset) của một Chuỗi, để tạo lại các Chuỗi này, nhưng với một Bộ mã khác, mô phỏng đầu vào ASCII đã đến với chúng ta ngay từ đầu:
String asciiSerbianString = new String(serbianString.getBytes(), StandardCharsets.US_ASCII);
String asciigermanString = new String(germanString.getBytes(), StandardCharsets.US_ASCII);
String asciijapaneseString = new String(japaneseString.getBytes(), StandardCharsets.US_ASCII);

System.out.println(asciiSerbianString);
System.out.println(asciigermanString);
System.out.println(asciijapaneseString);

Khi chúng tôi đã tạo các Chuỗi này và mã hóa chúng dưới dạng ký tự ASCII, chúng tôi có thể in chúng
��ta radi��?
Wie hei��en Sie?
������������������������������

Trong khi hai Chuỗi đầu tiên chỉ chứa một vài ký tự không phải là ký tự ASCII hợp lệ - chuỗi cuối cùng không chứa bất kỳ ký tự nào.

Để tránh vấn đề này, chúng tôi có thể giả định rằng không phải tất cả đầu vào có thể đã được mã hóa theo ý thích của chúng tôi - và mã hóa nó để tự khắc phục những trường hợp như vậy. Có một số cách chúng ta có thể tiến hành để mã hóa một chuỗi thành UTF-8 trong Java:
Mã hóa chuỗi trong Java đơn giản có nghĩa là đưa một số byte nhất định vào mảng byte tạo thành Chuỗi - cung cấp thông tin bổ sung có thể được sử dụng để định dạng nó khi chúng ta tạo một cá thể Chuỗi.

Encode a String to UTF-8 trong Java

Sử dụng phương thức getBytes ()

Lớp String, được tạo thành từ các byte, tự nhiên cung cấp một phương thức getBytes (), phương thức này trả về mảng byte được sử dụng để tạo Chuỗi. Vì mã hóa thực sự chỉ là thao tác với mảng byte này, chúng ta có thể đặt mảng này thông qua một Charset để tạo thành nó trong khi lấy dữ liệu.

Theo mặc định, không cung cấp Bộ mã, các byte được mã hóa bằng Bộ mã mặc định của nền tảng - có thể không phải là UTF-8 hoặc UTF-16. Hãy lấy các byte của một Chuỗi và in chúng ra:

String serbianString = "Šta radiš?"; // What are you doing?
byte[] bytes = serbianString.getBytes(StandardCharsets.UTF_8);

for (byte b : bytes) {
    System.out.print(String.format("%s ", b));
}

-59 -96 116 97 32 114 97 100 105 -59 -95 63

Đây là những điểm mã cho các ký tự được mã hóa của chúng tôi và chúng không thực sự hữu ích đối với mắt người. Mặc dù vậy, một lần nữa, chúng ta có thể tận dụng hàm tạo của String để tạo ra một Chuỗi mà con người có thể đọc được từ chính chuỗi này. Xem xét thực tế là chúng tôi đã mã hóa mảng byte này thành UTF_8, chúng tôi có thể tiếp tục và tạo một chuỗi mới một cách an toàn từ điều này:
String utf8String = new String(bytes);
System.out.println(utf8String);

Lưu ý: Thay vì mã hóa chúng thông qua phương thức getBytes (), bạn cũng có thể mã hóa các byte thông qua hàm tạo chuỗi:
Điều này bây giờ xuất ra cùng một Chuỗi mà chúng tôi đã bắt đầu, nhưng được mã hóa thành UTF-8
Mã hóa một chuỗi thành UTF-8 với Java 7 StandardCharsets
Kể từ Java 7, chúng tôi đã được giới thiệu với lớp StandardCharsets, lớp này có một số Bộ mã có sẵn như US_ASCII, ISO_8859_1, UTF_8 và UTF-16 trong số những bộ khác.

Mỗi Charset có một phương thức encode () và decode (), chấp nhận một CharBuffer (thực hiện CharSequence, giống như một Chuỗi). Về mặt thực tế - điều này có nghĩa là chúng ta có thể đưa một Chuỗi vào các phương thức encode () của một Charset.

Phương thức encode () trả về một ByteBuffer - mà chúng ta có thể dễ dàng biến lại thành một Chuỗi.

Trước đây khi chúng ta sử dụng phương thức getBytes (), chúng ta đã lưu trữ các byte mà chúng ta có trong một mảng các byte, nhưng khi sử dụng lớp StandardCharsets, mọi thứ có một chút khác biệt. Trước tiên, chúng ta cần sử dụng một lớp có tên là ByteBuffer để lưu trữ các byte của chúng ta. Sau đó, chúng ta cần phải mã hóa và sau đó giải mã lại các byte mới được cấp phát của chúng ta. Hãy xem cách này hoạt động trong mã
String japaneseString = "よろしくお願いします"; // Pleased to meet you.

ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(japaneseString);

String utf8String = new String(byteBuffer.array(), StandardCharsets.UTF_8);

System.out.println(utf8String);

Chạy mã này dẫn đến
よろしくお願いします

Mã hóa chuỗi thành UTF-8 với Apache Commons
Gói Apache Commons Codec chứa các bộ mã hóa và giải mã đơn giản cho các định dạng khác nhau như Base64 và Hexadecimal. Ngoài các bộ mã hóa và giải mã được sử dụng rộng rãi này, gói codec cũng duy trì một bộ sưu tập các tiện ích mã hóa phiên âm.

Để chúng tôi có thể sử dụng Apache Commons Codec, chúng tôi cần thêm nó vào dự án của mình như một phần phụ thuộc bên ngoài
Sử dụng Maven, hãy thêm phụ thuộc commons-codec vào tệp pom.xml của chúng tôi
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.15</version>
</dependency>

Ngoài ra, nếu bạn đang sử dụng Gradle:
compile 'commons-codec:commons-codec:1.15'

Bây giờ, chúng ta có thể sử dụng các lớp tiện ích của Apache Commons - và như thường lệ, chúng ta sẽ tận dụng lớp StringUtils.

Nó cho phép chúng ta chuyển đổi các Chuỗi thành và từ các byte bằng cách sử dụng các mã hóa khác nhau theo yêu cầu của đặc tả Java. Lớp này không an toàn và an toàn cho luồng, vì vậy chúng tôi có thêm một lớp bảo vệ khi làm việc với Chuỗi.

Để mã hóa một chuỗi thành UTF-8 bằng lớp StringUtils của Apache Common, chúng ta có thể sử dụng phương thức getBytesUtf8 (), có chức năng giống như phương thức getBytes () với một Charset được chỉ định:
String germanString = "Wie heißen Sie?"; // What's your name?
byte[] bytes = StringUtils.getBytesUtf8(germanString);
String utf8String = StringUtils.newStringUtf8(bytes);
System.out.println(utf8String);
Ket qua:
Wie heißen Sie?

Hoặc, bạn có thể sử dụng lớp StringUtils thông thường từ phụ thuộc commons-lang3
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
</dependency>

implementation group: 'org.apache.commons', name: 'commons-lang3', version: ${version}
Và bây giờ, chúng ta có thể sử dụng cách tiếp cận tương tự như với các Chuỗi thông thường
String germanString = "Wie heißen Sie?"; // What's your name?
byte[] bytes = StringUtils.getBytes(germanString, StandardCharsets.UTF_8);
String utf8String = StringUtils.toEncodedString(bytes, StandardCharsets.UTF_8);
System.out.println(utf8String);

Blogger Comments


Không có nhận xét nào. Chúc mừng bạn là người đầu tiên.

  • Kí tự đặc biệt
  • Tôi Share
  • Star Mạnh Blog
  • Văn Tuấn Blog
  • Tuổi Trẻ IT
  • Văn Thắng Blog
  • Duy Blogs
  • Star Sinh Blog
  • Lê Bá Long IT
  • Đặt liên kết
  • Đặt liên kết
  • Đặt liên kết