Có một cách dễ dàng để tránh xử lý các vấn đề mã hóa văn bản?
Bạn thực sự không thể tránh việc xử lý các vấn đề mã hóa văn bản, nhưng có các giải pháp hiện có:
Reader
thành InputStream
: ReaderInputStream
Writer
thành OutputStream
: WriterOutputStream
Bạn chỉ cần chọn mã hóa của sự lựa chọn của bạn.
Nếu bạn đang bắt đầu với Chuỗi, bạn cũng có thể làm như sau:
new ByteArrayInputStream(inputString.getBytes("UTF-8"))
Chà, một Reader xử lý các ký tự và một InputStream xử lý các byte. Mã hóa chỉ định cách bạn muốn thể hiện các ký tự của mình dưới dạng byte, vì vậy bạn thực sự không thể bỏ qua vấn đề. Để tránh các vấn đề, ý kiến của tôi là: chọn một bộ ký tự (ví dụ: "UTF-8") và gắn bó với nó.
Về cách thực sự làm điều đó, như đã được chỉ ra, " tên rõ ràng cho các lớp này là ReaderInputStream và WriterOutputStream. "Đáng ngạc nhiên," những thứ này không được bao gồm trong thư viện Java "ngay cả khi các lớp 'đối diện', InputStreamReader và - OutputStreamWriterare được bao gồm.
Vì vậy, rất nhiều người đã đưa ra các triển khai của riêng họ, bao gồm ApacheCommons IO . Tùy thuộc vào các vấn đề cấp phép, bạn có thể sẽ bao gồm thư viện commons-io trong dự án của mình hoặc thậm chí sao chép một phần mã nguồn (có thể tải xuống tại đây ).
Như bạn có thể thấy, tài liệu của cả hai lớp nói rằng "tất cả các bảng mã được hỗ trợ bởi JRE đều được xử lý chính xác".
N.B. Một nhận xét về một trong những câu trả lời khác ở đây đề cập đến lỗi này . Nhưng điều đó ảnh hưởng đến lớp Apache Ant ReaderInputStream ( ở đây ), không lớp Apache Commons IO Lớp ReaderInputStream.
Cũng lưu ý rằng, nếu bạn bắt đầu với Chuỗi, bạn có thể bỏ qua việc tạo StringReader và tạo InputStream trong một bước bằng cách sử dụng org.Apache.commons.io.IOUtils từ Commons IO như vậy:
InputStream myInputStream = IOUtils.toInputStream(reportContents, "UTF-8");
Tất nhiên bạn vẫn cần phải suy nghĩ về mã hóa văn bản, nhưng ít nhất việc chuyển đổi đang diễn ra trong một bước.
Sử dụng:
new CharSequenceInputStream(html, StandardCharsets.UTF_8);
Cách này không yêu cầu chuyển đổi trả trước thành String
và sau đó thành byte[]
, phân bổ bộ nhớ heap nhiều hơn, trong trường hợp báo cáo lớn. Nó chuyển đổi thành byte khi đang đọc khi luồng được đọc, ngay từ StringBuffer.
Nó sử dụng CharSequenceInputStream từ dự án Apache Commons IO.
Bạn không thể tránh các vấn đề mã hóa văn bản, nhưng Apache commons-io có
Lưu ý đây là những thư viện được đề cập trong câu trả lời của Peter trên koders.com, chỉ liên kết đến thư viện thay vì mã nguồn.
Tên rõ ràng cho các lớp này là ReaderInputStream và WriterOutputStream. Thật không may, những thứ này không được bao gồm trong thư viện Java. Tuy nhiên, google là bạn của bạn.
Tôi không chắc chắn rằng nó sẽ khắc phục được tất cả các vấn đề về mã hóa văn bản, vốn là ác mộng.
Có RFE, nhưng nó đã đóng, sẽ không sửa.
Bạn có đang cố gắng viết nội dung của một Reader
thành một OutputStream
không? Nếu vậy, bạn sẽ có thời gian dễ dàng hơn để bọc OutputStream
trong một OutputStreamWriter
và viết char
s từ Reader
vào Writer
, thay vì thử để chuyển đổi đầu đọc thành InputStream
:
final Writer writer = new BufferedWriter(new OutputStreamWriter( urlConnection.getOutputStream(), "UTF-8" ) );
int charsRead;
char[] cbuf = new char[1024];
while ((charsRead = data.read(cbuf)) != -1) {
writer.write(cbuf, 0, charsRead);
}
writer.flush();
// don't forget to close the writer in a finally {} block
Bạn có thể sử dụng Cactoos (không có phương thức tĩnh, chỉ các đối tượng):
Bạn cũng có thể chuyển đổi theo cách khác:
Một cảnh báo khi sử dụng WriterOutputStream - nó không phải lúc nào cũng xử lý việc ghi dữ liệu nhị phân vào một tệp đúng/giống như một luồng đầu ra thông thường. Tôi có một vấn đề với điều này khiến tôi mất một lúc để theo dõi.
Nếu bạn có thể, tôi khuyên bạn nên sử dụng luồng đầu ra làm cơ sở của mình và nếu bạn cần viết chuỗi, hãy sử dụng trình bao bọc OUtputStreamWriter xung quanh luồng để thực hiện. Việc chuyển đổi văn bản thành byte đáng tin cậy hơn nhiều so với cách khác, đó có thể là lý do tại sao WriterOutputStream không phải là một phần của thư viện Java tiêu chuẩn