Sichere Codierungskonstruktoren
Es ist schwierig, Java dazu zu bringen, Sie ordnungsgemäß über Codierungsfehler zu benachrichtigen. Sie müssen den ausführlichsten und leider den am wenigsten verwendeten der vier alternativen Konstruktoren für jeden von InputStreamReader
und verwenden OutputStreamWriter
, um eine ordnungsgemäße Ausnahme für einen Codierungsfehler zu erhalten.
Stellen Sie für Datei-E / A immer sicher, dass Sie immer das zweite Argument für beide OutputStreamWriter
und InputStreamReader
das ausgefallene Encoder-Argument verwenden:
Charset.forName("UTF-8").newEncoder()
Es gibt andere, noch schickere Möglichkeiten, aber keine der drei einfacheren Möglichkeiten funktioniert für die Ausnahmebehandlung. Diese tun:
OutputStreamWriter char_output = new OutputStreamWriter(
new FileOutputStream("some_output.utf8"),
Charset.forName("UTF-8").newEncoder()
);
InputStreamReader char_input = new InputStreamReader(
new FileInputStream("some_input.utf8"),
Charset.forName("UTF-8").newDecoder()
);
Wie zum Laufen mit
$ java -Dfile.encoding=utf8 SomeTrulyRemarkablyLongcLassNameGoeShere
Das Problem ist, dass dadurch nicht das vollständige Encoder-Argument für die Zeichenströme verwendet wird und Sie erneut Codierungsprobleme verpassen.
Längeres Beispiel
Hier ist ein längeres Beispiel, das einen Prozess anstelle einer Datei verwaltet, in dem zwei verschiedene Eingabebyte-Streams und ein Ausgabebyte-Stream mit vollständiger Ausnahmebehandlung in UTF-8-Zeichenströme umgewandelt werden :
Process
slave_process = Runtime.getRuntime().exec("perl -CS script args");
OutputStream
__bytes_into_his_stdin = slave_process.getOutputStream();
OutputStreamWriter
chars_into_his_stdin = new OutputStreamWriter(
__bytes_into_his_stdin,
Charset.forName("UTF-8").newEncoder()
);
InputStream
__bytes_from_his_stdout = slave_process.getInputStream();
InputStreamReader
chars_from_his_stdout = new InputStreamReader(
__bytes_from_his_stdout,
Charset.forName("UTF-8").newDecoder()
);
InputStream
__bytes_from_his_stderr = slave_process.getErrorStream();
InputStreamReader
chars_from_his_stderr = new InputStreamReader(
__bytes_from_his_stderr,
Charset.forName("UTF-8").newDecoder()
);
Jetzt haben Sie drei Zeichenströme , dass alle raise Ausnahmefehler auf kodieren jeweils genannt chars_into_his_stdin
, chars_from_his_stdout
und chars_from_his_stderr
.
Dies ist nur geringfügig komplizierter als das, was Sie für Ihr Problem benötigen, dessen Lösung ich in der ersten Hälfte dieser Antwort gegeben habe. Der entscheidende Punkt ist, dass dies die einzige Möglichkeit ist, Codierungsfehler zu erkennen.
Lass mich nur nicht damit anfangen PrintStream
, Ausnahmen zu essen.
InputStreamReader char_input = new InputStreamWriter
sollte lauten:InputStreamReader char_input = new InputStreamReader
und derInputStreamReader
Konstruktor nimmt einCharsetDecoder
, keinCharsetEncoder
.CipherInputStream
, diese zu entfernenBadPaddingException
, auch wenn sie von einem authentifizierten Chiffrestream erstellt wurden :(Ditch
FileWriter
undFileReader
, die genau deshalb nutzlos sind, weil Sie die Codierung nicht angeben können. Verwenden Sie stattdessennew OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)
und
new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
quelle
Charset.forName("UTF-8").newDecoder()
Argument (oder ein ausgefalleneres Konstrukt) verwenden"UTF-8"
, werden Sie nicht ordnungsgemäß über Codierungsfehler informiert (lesen Sie: Ausnahmen werden unterdrückt und Codierungsfehler werden auf mysteriöse Weise ausgeblendet).new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8 )
Sie müssen die
OutputStreamWriter
Klasse als Writer-Parameter für Ihre verwendenBufferedWriter
. Es akzeptiert eine Codierung. Überprüfen Sie Javadocs dafür.Etwas wie folgt:
BufferedWriter out = new BufferedWriter(new OutputStreamWriter( new FileOutputStream("jedis.txt"), "UTF-8" ));
Oder Sie können die aktuelle Systemcodierung mit der Systemeigenschaft
file.encoding
auf UTF-8 setzen.java -Dfile.encoding=UTF-8 com.jediacademy.Runner arg1 arg2 ...
Sie können es auch zur Laufzeit als Systemeigenschaft festlegen,
System.setProperty(...)
wenn Sie es nur für diese bestimmte Datei benötigen, aber in einem solchen Fall würde ich das bevorzugenOutputStreamWriter
.Wenn Sie die Systemeigenschaft festlegen, können Sie
FileWriter
davon ausgehen, dass UTF-8 als Standardcodierung für Ihre Dateien verwendet wird. In diesem Fall für alle Dateien, die Sie lesen und schreiben.BEARBEITEN
Ab API 19 können Sie den String "UTF-8" durch ersetzen
StandardCharsets.UTF_8
Wie in den Kommentaren von tchrist unten vorgeschlagen , müssen Sie, wenn Sie Codierungsfehler in Ihrer Datei erkennen möchten, den
OutputStreamWriter
Ansatz verwenden und den Konstruktor verwenden, der einen Zeichensatzcodierer empfängt.Etwas wie
CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder(); encoder.onMalformedInput(CodingErrorAction.REPORT); encoder.onUnmappableCharacter(CodingErrorAction.REPORT); BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("jedis.txt"),encoder));
Sie können zwischen Aktionen wählen
IGNORE | REPLACE | REPORT
Außerdem wurde diese Frage schon beantwortet hier .
quelle
InputStreamReader(InputStream in, CharsetDecoder dec)
, so dass das letzte Argument istCharset.forName("UTF-8").newDecoder()
.{In,Out}putStream{Reader,Writer}
Konstruktoren auf fehlerhafte Daten testen , werden Sie feststellen, dass drei von ihnen alle Ausnahmen maskieren , die sich aus Codierungsfehlern ergeben sollten , und nur die vierte Form liefert sie Ihnen korrekt. Darum geht esCharset.forName("UTF-8").newDecoder()
. Ich erkläre dies ein wenig in meiner Antwort.Seit Java 11 können Sie:
FileWriter fw = new FileWriter("filename.txt", Charset.forName("utf-8"));
quelle
Seit Java 7 gibt es eine einfache Möglichkeit, die Zeichencodierung von BufferedWriter und BufferedReaders zu handhaben. Sie können einen BufferedWriter direkt mithilfe der Files-Klasse erstellen, anstatt verschiedene Instanzen von Writer zu erstellen. Sie können einfach einen BufferedWriter erstellen, der die Zeichenkodierung berücksichtigt, indem Sie Folgendes aufrufen:
Weitere Informationen finden Sie in JavaDoc:
quelle
Mit chinesischem Text habe ich versucht, das Charset UTF-16 zu verwenden, und zum Glück funktioniert es.
Hoffe das könnte helfen!
PrintWriter out = new PrintWriter( file, "UTF-16" );
quelle
OK, es ist jetzt 2019 und ab Java 11 haben Sie einen Konstruktor mit Charset:
quelle
Verwenden Sie OutputStream anstelle von FileWriter, um den Codierungstyp festzulegen
// file is your File object where you want to write you data OutputStream outputStream = new FileOutputStream(file); OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, "UTF-8"); outputStreamWriter.write(json); // json is your data outputStreamWriter.flush(); outputStreamWriter.close();
quelle
Meiner Meinung nach
Wenn Sie schreiben möchten , folgen Sie der folgenden Art von UTF-8. Sie sollten ein Byte-Array erstellen. Dann können Sie Folgendes tun:
byte[] by=("<?xml version=\"1.0\" encoding=\"utf-8\"?>"+"Your string".getBytes();
Anschließend können Sie jedes Byte in die von Ihnen erstellte Datei schreiben. Beispiel:
OutputStream f=new FileOutputStream(xmlfile); byte[] by=("<?xml version=\"1.0\" encoding=\"utf-8\"?>"+"Your string".getBytes(); for (int i=0;i<by.length;i++){ byte b=by[i]; f.write(b); } f.close();
quelle