Bir Okuyucuyu InputStream'e ve bir Yazarı OutputStream'e nasıl dönüştürebilirim?


89

Metin kodlama sorunlarıyla uğraşmaktan kaçınmanın kolay bir yolu var mı?

Yanıtlar:


46

Metin kodlama sorunlarıyla uğraşmaktan gerçekten kaçınamazsınız, ancak Apache Commons'ta mevcut çözümler vardır:

Sadece seçtiğiniz kodlamayı seçmeniz gerekiyor.


7
Bilginize: ReaderInputStream kodunun bayt okuma biçiminde bir hatası var (tüm kodlamalar için çalışmayacaktır). Kanıt: illegalargumentexception.blogspot.com/2009/05/... açık hata vardır: issues.apache.org/bugzilla/show_bug.cgi?id=40455
McDowell

1
Sınıfları Apache'nin commons-io kütüphanesinde bulabilirsiniz: commons.apache.org/proper/commons-io
AlikElzin-kilaka

@McDowell, bahsettiğiniz hata Apache Ant'ın uygulamasında, commons-io'larda değil, bu yüzden bu yanıtla alakalı değil.
Roman

94

Bir String ile başlıyorsanız, aşağıdakileri de yapabilirsiniz:

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

7
İyi bir ReaderInputStreamuygulama daha az bellek gerektirir - tüm baytları bir dizide aynı anda depolamaya gerek olmamalıdır.
Piotr Findeisen

3
Bu çözümü beğendim, çünkü standart girişte (örneğin) girişi kabul eden kodu test etmeniz gerektiğinde işe yarıyor.
Kedar Mhaswade

43

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 .


19

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.


4
Bu yöntem temelde 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.
Oliv

8

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 Stringve 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 .



5

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.


1
bugs.openjdk.java.net/browse/JDK-4103785 , "karakter kümesi kodlaması için genel bir API'miz var ... bu sınıfları eklemek için zorlayıcı bir nedenimiz yok" yorumunu içerir - bu, Java 7'de ek olmadan nasıl yapılır Kütüphaneler, on iki yıl geride mi?
Piotr Findeisen


4

Bir içeriğini yazmaya çalışıyorsunuz Readerbir etmek OutputStream? Eğer öyleyse, daha kolay bir zaman sarma olacak OutputStreambir in OutputStreamWriterve yazma chargelen s Readeriçin Writeryerine 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

1

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.



-1

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")));

6
ReaderInputStream, Apache Commons IO'da.
Will Beason
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.