Bagaimana cara mengonversi Pembaca ke InputStream dan Penulis menjadi OutputStream?


89

Apakah ada cara mudah untuk menghindari masalah pengkodean teks?

Jawaban:


46

Anda tidak dapat benar-benar menghindari berurusan dengan masalah pengkodean teks, tetapi ada solusi yang ada di Apache Commons:

Anda hanya perlu memilih pengkodean pilihan Anda.


7
FYI: kode ReaderInputStream memiliki bug dalam cara membaca byte (tidak akan bekerja untuk semua pengkodean). Bukti: illegalargumentexception.blogspot.com/2009/05/… Ada bug terbuka: issues.apache.org/bugzilla/show_bug.cgi?id=40455
McDowell

1
Anda dapat menemukan kelas-kelas di perpustakaan commons-io Apache: commons.apache.org/proper/commons-io
AlikElzin-kilaka

@McDowell, bug yang Anda sebutkan ada di implementasi Apache Ant, bukan di commons-io's, jadi tidak relevan dengan jawaban ini.
Roman

94

Jika Anda memulai dengan String, Anda juga dapat melakukan hal berikut:

new ByteArrayInputStream(inputString.getBytes("UTF-8"))

7
ReaderInputStreamImplementasi yang baik akan membutuhkan lebih sedikit memori - seharusnya tidak perlu menyimpan semua byte dalam array sekaligus.
Piotr Findeisen

3
Saya suka solusi ini karena berfungsi ketika Anda perlu kode uji unit yang menerima input pada (misalnya) input standar.
Kedar Mhaswade

43

Nah, Pembaca berurusan dengan karakter dan InputStream berurusan dengan byte. Pengkodean menentukan bagaimana Anda ingin merepresentasikan karakter Anda sebagai byte, jadi Anda tidak bisa mengabaikan masalah ini. Adapun untuk menghindari masalah, pendapat saya adalah: pilih satu rangkaian karakter (misalnya "UTF-8") dan pertahankan.

Mengenai bagaimana sebenarnya melakukannya, seperti yang telah ditunjukkan, " nama yang jelas untuk kelas ini adalah ReaderInputStream dan WriterOutputStream . " Anehnya, " ini tidak termasuk dalam pustaka Java " meskipun kelas 'berlawanan', InputStreamReader dan OutputStreamWriter adalah termasuk.

Jadi, banyak orang yang membuat implementasinya sendiri, termasuk Apache Commons IO . Bergantung pada masalah lisensi, Anda mungkin dapat menyertakan pustaka commons-io dalam proyek Anda, atau bahkan menyalin sebagian dari kode sumber (yang dapat diunduh di sini ).

Seperti yang Anda lihat, dokumentasi kedua kelas menyatakan bahwa "semua encoding charset yang didukung oleh JRE ditangani dengan benar".

NB Sebuah komentar di salah satu jawaban lain di sini menyebutkan bug ini . Tapi itu memengaruhi kelas Apache Ant ReaderInputStream (di sini ), bukan kelas Apache Commons IO ReaderInputStream.


19

Perhatikan juga bahwa, jika Anda memulai dengan String, Anda dapat melewati pembuatan StringReader dan membuat InputStream dalam satu langkah menggunakan org.apache.commons.io.IOUtils dari Commons IO seperti:

InputStream myInputStream = IOUtils.toInputStream(reportContents, "UTF-8");

Tentu Anda masih perlu memikirkan tentang pengkodean teks, tetapi setidaknya konversi terjadi dalam satu langkah.


4
Metode ini pada dasarnya new ByteArrayInputStream(report.toString().getBytes("utf-8")), yang melibatkan alokasi dua salinan tambahan dari laporan dalam memori. Jika laporannya besar, itu buruk. Lihat jawabanku.
Oliv

8

Menggunakan:

new CharSequenceInputStream(html, StandardCharsets.UTF_8);

Cara ini tidak memerlukan konversi dimuka ke Stringdan kemudian ke byte[], yang mengalokasikan lebih banyak memori heap, jika laporannya besar. Ini mengubah menjadi byte dengan cepat saat aliran dibaca, langsung dari StringBuffer.

Ini menggunakan CharSequenceInputStream dari proyek Apache Commons IO.



5

Nama yang jelas untuk kelas ini adalah ReaderInputStream dan WriterOutputStream. Sayangnya ini tidak termasuk dalam perpustakaan Java. Bagaimanapun, google adalah temanmu.

Saya tidak yakin bahwa ini akan mengatasi semua masalah pengkodean teks, yang merupakan mimpi buruk.

Ada RFE, tapi Ditutup, tidak akan diperbaiki.


1
bugs.openjdk.java.net/browse/JDK-4103785 berisi komentar "kami memiliki API publik untuk pengkodean kumpulan karakter ... tidak ada alasan kuat untuk menambahkan kelas-kelas ini" - jadi bagaimana seseorang melakukannya di Java 7, tanpa tambahan perpustakaan, dua belas tahun ke depan?
Piotr Findeisen


4

Apakah Anda mencoba menulis konten a Readerke an OutputStream? Jika demikian, Anda akan memiliki waktu lebih mudah membungkus OutputStreamdalam OutputStreamWriterdan menulis chars dari Readerke Writer, alih-alih mencoba untuk mengkonversi pembaca ke 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

1

Peringatan saat menggunakan WriterOutputStream - tidak selalu menangani penulisan data biner ke file dengan benar / sama dengan aliran keluaran biasa. Saya memiliki masalah dengan hal ini yang memerlukan beberapa saat untuk saya lacak.

Jika Anda bisa, saya sarankan untuk menggunakan aliran keluaran sebagai basis Anda, dan jika Anda perlu menulis string, gunakan pembungkus OUtputStreamWriter di sekitar aliran untuk melakukannya. Jauh lebih dapat diandalkan untuk mengonversi teks menjadi byte daripada sebaliknya, yang mungkin menjadi alasan WriterOutputStream bukan bagian dari pustaka Java standar



-1

Untuk Membaca string dalam aliran hanya menggunakan apa yang disediakan java.

InputStream s = new BufferedInputStream( new ReaderInputStream( new StringReader("a string")));

6
ReaderInputStream ada di Apache Commons IO.
Akan Beason
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.