web-development-kb-asia.site

Làm cách nào để chuyển đổi Reader thành InputStream và Writer thành OutputStream?

Có một cách dễ dàng để tránh xử lý các vấn đề mã hóa văn bản?

87
Andrei Savu

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ó:

Bạn chỉ cần chọn mã hóa của sự lựa chọn của bạn.

43
Peter

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"))
93
Ritesh Tendulkar

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à ReaderInputStreamWriterOutputStream. "Đá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.

41
Peter Ford

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.

19
Phil Harvey

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.

8
Oliv
7
Bozho

Bạn không thể tránh các vấn đề mã hóa văn bản, nhưng Apache commons-io

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.

5
dfrankow

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.

5
Tom Hawtin - tackline

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 chars 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
4
Sam Barnum

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:

1
yegor256

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

1
romeara