Metin kodlama sorunlarıyla uğraşmaktan kaçınmanın kolay bir yolu var mı?
Metin kodlama sorunlarıyla uğraşmaktan kaçınmanın kolay bir yolu var mı?
Yanıtlar:
Metin kodlama sorunlarıyla uğraşmaktan gerçekten kaçınamazsınız, ancak Apache Commons'ta mevcut çözümler vardır:
Reader
to InputStream
:ReaderInputStream
Writer
to OutputStream
:WriterOutputStream
Sadece seçtiğiniz kodlamayı seçmeniz gerekiyor.
Bir String ile başlıyorsanız, aşağıdakileri de yapabilirsiniz:
new ByteArrayInputStream(inputString.getBytes("UTF-8"))
ReaderInputStream
uygulama daha az bellek gerektirir - tüm baytları bir dizide aynı anda depolamaya gerek olmamalıdır.
Okuyucu karakterlerle ve bir InputStream baytlarla ilgilenir. Kodlama, karakterlerinizi bayt olarak nasıl temsil etmek istediğinizi belirtir, bu nedenle sorunu gerçekten göz ardı edemezsiniz. Sorunlardan kaçınmaya gelince, benim fikrim: bir karakter seti seçin (örneğin "UTF-8") ve ona bağlı kalın.
Aslında bunu nasıl yanı işaret edilmiştir ilgili olarak, " Bu sınıflar için bariz isimler ReaderInputStream ve WriterOutputStream . " Hayret, " Bu Java kütüphanesi dahil değildir 'ters' sınıfları, olsa bile" InputStreamReader ve OutputStreamWriter vardır dahil.
Bu nedenle, Apache Commons IO da dahil olmak üzere birçok kişi kendi uygulamalarını geliştirdi . Lisans sorunlarına bağlı olarak, muhtemelen projenize commons-io kitaplığını dahil edebilecek veya hatta kaynak kodunun bir bölümünü kopyalayabileceksiniz ( buradan indirilebilir ).
Gördüğünüz gibi, her iki sınıfın dokümantasyonu "JRE tarafından desteklenen tüm karakter kümesi kodlamalarının doğru şekilde işlendiğini" belirtir.
NB Buradaki diğer yanıtlardan birine yapılan yorum bu hatadan bahsediyor . Ancak bu , Apache Commons IO ReaderInputStream sınıfını değil , Apache Ant ReaderInputStream sınıfını ( burada ) etkiler .
Ayrıca, bir String ile başlıyorsanız, Commons IO'dan org.apache.commons.io.IOUtils kullanarak tek adımda bir StringReader oluşturmayı atlayabilir ve bir InputStream oluşturabilirsiniz :
InputStream myInputStream = IOUtils.toInputStream(reportContents, "UTF-8");
Elbette yine de metin kodlaması hakkında düşünmeniz gerekiyor, ancak en azından dönüştürme tek adımda gerçekleşiyor.
new ByteArrayInputStream(report.toString().getBytes("utf-8"))
, raporun iki ek kopyasının bellekte tahsis edilmesini içerir. Rapor büyükse, kötüdür. Cevabımı gör.
Kullanım:
new CharSequenceInputStream(html, StandardCharsets.UTF_8);
Bu yol , raporun büyük olması durumunda çok daha fazla yığın belleği ayıran önden String
ve ardından önden dönüştürmeyi gerektirmez byte[]
. Akış okundukça, doğrudan StringBuffer'dan anında bayta dönüşür.
Apache Commons IO projesinden CharSequenceInputStream kullanır .
Bu sınıflar için bariz isimler ReaderInputStream ve WriterOutputStream'dir. Ne yazık ki bunlar Java kitaplığına dahil edilmemiştir. Ancak, google senin arkadaşın.
Kabus gibi tüm metin kodlama problemlerinin üstesinden gelip gelmeyeceğinden emin değilim.
Bir RFE var, ancak Kapalı, düzeltilmeyecek.
Sorunların kodlayan metni kaçınamaz ama Apache commons-io vardır
Bunlar, Peter'ın koders.com'daki yanıtında belirtilen kütüphanelerdir, sadece kaynak kodu yerine kütüphaneye bağlanır.
Bir içeriğini yazmaya çalışıyorsunuz Reader
bir etmek OutputStream
? Eğer öyleyse, daha kolay bir zaman sarma olacak OutputStream
bir in OutputStreamWriter
ve yazma char
gelen s Reader
için Writer
yerine okuyucuyu dönüştürmek çalışmakla, 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
WriterOutputStream kullanılırken bir uyarı - ikili verilerin bir dosyaya yazılması her zaman düzgün / normal bir çıktı akışı ile aynı şekilde işlemez. Bununla ilgili, bulmam biraz zaman alan bir sorun yaşadım.
Yapabiliyorsanız, temeliniz olarak bir çıkış akışı kullanmanızı öneririm ve dizeler yazmanız gerekiyorsa, bunu yapmak için akışın etrafında bir OUtputStreamWriter sarıcı kullanın. Metni bayta dönüştürmek, tersine çevirmekten çok daha güvenilirdir, bu nedenle WriterOutputStream, standart Java kitaplığının bir parçası değildir.
Cactoos kullanabilirsiniz (statik yöntem yok, yalnızca nesneler):
Diğer yolu da dönüştürebilirsiniz:
Sadece java'nın sağladığını kullanarak bir akıştaki dizeyi okumak için.
InputStream s = new BufferedInputStream( new ReaderInputStream( new StringReader("a string")));