Apakah ada cara mudah untuk menghindari masalah pengkodean teks?
89
Anda tidak dapat benar-benar menghindari berurusan dengan masalah pengkodean teks, tetapi ada solusi yang ada di Apache Commons:
Reader
kepada InputStream
:ReaderInputStream
Writer
kepada OutputStream
:WriterOutputStream
Anda hanya perlu memilih pengkodean pilihan Anda.
Jika Anda memulai dengan String, Anda juga dapat melakukan hal berikut:
new ByteArrayInputStream(inputString.getBytes("UTF-8"))
sumber
ReaderInputStream
Implementasi yang baik akan membutuhkan lebih sedikit memori - seharusnya tidak perlu menyimpan semua byte dalam array sekaligus.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.
sumber
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.
sumber
new ByteArrayInputStream(report.toString().getBytes("utf-8"))
, yang melibatkan alokasi dua salinan tambahan dari laporan dalam memori. Jika laporannya besar, itu buruk. Lihat jawabanku.Menggunakan:
new CharSequenceInputStream(html, StandardCharsets.UTF_8);
Cara ini tidak memerlukan konversi dimuka ke
String
dan kemudian kebyte[]
, 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.
sumber
commons-io 2.0 memiliki
WriterOutputStream
sumber
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.
sumber
Anda tidak dapat menghindari masalah pengkodean teks, tetapi Apache commons-io memilikinya
Perhatikan bahwa ini adalah perpustakaan yang dirujuk dalam jawaban Peter di koders.com, cukup tautan ke perpustakaan alih-alih kode sumber.
sumber
Apakah Anda mencoba menulis konten a
Reader
ke anOutputStream
? Jika demikian, Anda akan memiliki waktu lebih mudah membungkusOutputStream
dalamOutputStreamWriter
dan menulischar
s dariReader
keWriter
, alih-alih mencoba untuk mengkonversi pembaca keInputStream
: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
sumber
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
sumber
Anda dapat menggunakan Cactoos (tanpa metode statis, hanya objek):
new InputStreamOf(reader)
new OutputStreamTo(writer)
Anda juga dapat mengonversi sebaliknya:
new ReaderOf(inputStream)
new WriterTo(outputStream)
sumber
Untuk Membaca string dalam aliran hanya menggunakan apa yang disediakan java.
InputStream s = new BufferedInputStream( new ReaderInputStream( new StringReader("a string")));
sumber