Gibt es eine einfache Möglichkeit, Probleme mit der Textcodierung zu vermeiden?
Gibt es eine einfache Möglichkeit, Probleme mit der Textcodierung zu vermeiden?
Antworten:
Sie können es nicht wirklich vermeiden, sich mit den Problemen der Textcodierung zu befassen, aber in Apache Commons gibt es bereits Lösungen:
Reader
zu InputStream
:ReaderInputStream
Writer
zu OutputStream
:WriterOutputStream
Sie müssen nur die Codierung Ihrer Wahl auswählen.
Wenn Sie mit einem String beginnen, können Sie auch Folgendes tun:
new ByteArrayInputStream(inputString.getBytes("UTF-8"))
ReaderInputStream
Implementierung würde weniger Speicher erfordern - es sollten nicht alle Bytes gleichzeitig in einem Array gespeichert werden müssen.
Nun, ein Reader befasst sich mit Zeichen und ein InputStream mit Bytes. Die Codierung gibt an, wie Sie Ihre Zeichen als Bytes darstellen möchten, sodass Sie das Problem nicht wirklich ignorieren können. Um Probleme zu vermeiden, ist meine Meinung: Wählen Sie einen Zeichensatz (z. B. "UTF-8") und bleiben Sie dabei.
Wie bereits erwähnt, lauten die offensichtlichen Namen für diese Klassen ReaderInputStream und WriterOutputStream . Überraschenderweise sind diese nicht in der Java-Bibliothek enthalten , obwohl die entgegengesetzten Klassen InputStreamReader und OutputStreamWriter verwendet werden inbegriffen.
Viele Leute haben sich ihre eigenen Implementierungen ausgedacht, einschließlich Apache Commons IO . Abhängig von Lizenzproblemen können Sie wahrscheinlich die Commons-Io-Bibliothek in Ihr Projekt aufnehmen oder sogar einen Teil des Quellcodes kopieren (der hier heruntergeladen werden kann ).
Wie Sie sehen können, heißt es in der Dokumentation beider Klassen, dass "alle von der JRE unterstützten Zeichensatzcodierungen korrekt behandelt werden".
NB Ein Kommentar zu einer der anderen Antworten hier erwähnt diesen Fehler . Dies betrifft jedoch die Apache Ant ReaderInputStream-Klasse ( hier ) und nicht die Apache Commons IO ReaderInputStream-Klasse.
Beachten Sie außerdem, dass Sie, wenn Sie mit einem String beginnen, das Erstellen eines StringReader überspringen und in einem Schritt einen InputStream erstellen können, indem Sie org.apache.commons.io.IOUtils von Commons IO wie folgt verwenden :
InputStream myInputStream = IOUtils.toInputStream(reportContents, "UTF-8");
Natürlich müssen Sie noch über die Textcodierung nachdenken, aber zumindest erfolgt die Konvertierung in einem Schritt.
new ByteArrayInputStream(report.toString().getBytes("utf-8"))
die Zuweisung von zwei zusätzlichen Kopien des Berichts im Speicher. Wenn der Bericht groß ist, ist er schlecht. Siehe meine Antwort.
Verwenden:
new CharSequenceInputStream(html, StandardCharsets.UTF_8);
Auf diese Weise ist keine Vorabkonvertierung nach String
und dann nach erforderlich byte[]
, wodurch viel mehr Heapspeicher zugewiesen wird, falls der Bericht groß ist. Es wird im laufenden Betrieb in Bytes konvertiert, wenn der Stream direkt aus dem StringBuffer gelesen wird.
Es verwendet CharSequenceInputStream aus dem Apache Commons IO-Projekt.
Die offensichtlichen Namen für diese Klassen sind ReaderInputStream und WriterOutputStream. Leider sind diese nicht in der Java-Bibliothek enthalten. Google ist jedoch dein Freund.
Ich bin mir nicht sicher, ob es alle alptraumhaften Textcodierungsprobleme umgehen wird.
Es gibt eine RFE, jedoch geschlossen ist und nicht behoben werden kann.
Sie können Probleme mit der Textcodierung nicht vermeiden, Apache commons-io jedoch
Beachten Sie, dass dies die Bibliotheken sind, auf die in Peters Antwort von koders.com Bezug genommen wird, sondern nur Links zur Bibliothek anstelle des Quellcodes.
Versuchen Sie, den Inhalt von a Reader
in ein zu schreiben OutputStream
? In diesem Fall fällt es Ihnen leichter , das s OutputStream
in ein zu wickeln OutputStreamWriter
und das char
s von dem Reader
in das zu schreiben Writer
, anstatt zu versuchen, den Reader in einen zu konvertieren 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
Eine Warnung bei Verwendung von WriterOutputStream - das Schreiben von Binärdaten in eine Datei wird nicht immer ordnungsgemäß ausgeführt / genauso wie bei einem normalen Ausgabestream. Ich hatte ein Problem damit, das ich eine Weile brauchte, um es aufzuspüren.
Wenn Sie können, würde ich empfehlen, einen Ausgabestream als Basis zu verwenden. Wenn Sie Zeichenfolgen schreiben müssen, verwenden Sie dazu einen OUtputStreamWriter-Wrapper um den Stream. Das Konvertieren von Text in Bytes ist weitaus zuverlässiger als umgekehrt, weshalb WriterOutputStream wahrscheinlich nicht Teil der Standard-Java-Bibliothek ist
Sie können Kakteen verwenden (keine statischen Methoden, nur Objekte):
Sie können auch umgekehrt konvertieren:
Zum Lesen eines Strings in einem Stream mit genau dem, was Java liefert.
InputStream s = new BufferedInputStream( new ReaderInputStream( new StringReader("a string")));