2012-03-24 9 views
61

Ich habe den folgenden Code aber ich es als UTF-8-Datei schreiben möchten fremde Zeichen zu behandeln. Gibt es einen Weg, dies zu tun, gibt es eine Notwendigkeit, einen Parameter zu haben?Schreiben Sie eine Datei in UTF-8 mit FileWriter (Java)?

Ich würde wirklich Ihre Hilfe bei dieser zu schätzen wissen. Vielen Dank.

try { 
    BufferedReader reader = new BufferedReader(new FileReader("C:/Users/Jess/My Documents/actresses.list")); 
    writer = new BufferedWriter(new FileWriter("C:/Users/Jess/My Documents/actressesFormatted.csv")); 
    while((line = reader.readLine()) != null) { 
    //If the line starts with a tab then we just want to add a movie 
    //using the current actor's name. 
    if(line.length() == 0) 
     continue; 
    else if(line.charAt(0) == '\t') { 
     readMovieLine2(0, line, surname.toString(), forename.toString()); 
    } //Else we've reached a new actor 
    else { 
     readActorName(line); 
    } 
    } 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

Antwort

42

Sie benötigen die OutputStreamWriter Klasse, die als Schriftsteller Parameter für Ihre BufferedWriter zu verwenden. Es akzeptiert eine Codierung. Überprüfen Sie javadocs dafür.

Etwas wie folgt aus:

BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
    new FileOutputStream("jedis.txt"), "UTF-8" 
)); 

Oder Sie können das aktuelle System-Codierung mit der Systemeigenschaft file.encoding auf UTF-8 gesetzt.

java -Dfile.encoding=UTF-8 com.jediacademy.Runner arg1 arg2 ... 

Sie können auch mit System.setProperty(...) zur Laufzeit als System Eigenschaft es, wenn Sie es für diese bestimmte Datei benötigen, aber in einem Fall wie diesem ich glaube, ich würde die OutputStreamWriter bevorzugen.

Durch das System-Eigenschaft können Sie FileWriter und erwarten verwenden, dass es UTF-8 als Standardcodierung für Ihre Dateien verwenden. In diesem Fall für alle Dateien, die Sie lesen und schreiben.

EDIT

  • von Start API 19, können Sie den String ersetzen "UTF-8" mit StandardCharsets.UTF_8

  • Wie tchrist in den Kommentaren unten vorgeschlagen, wenn Sie zu erkennen beabsichtigen Codierungsfehler in der Datei würden Sie den OutputStreamWriter Ansatz zu verwenden, gezwungen und verwenden Sie den Konstruktor, der einen charset Encoder 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)); 
    

    können Sie zwischen Aktionen wählen IGNORE | REPLACE | REPORT

Auch wurde diese Frage bereits beantwortet here.

+0

Das ist nicht genug . Sie benötigen auch einen 'InputStreamReader (InputStream in, CharsetDecoder dec)', so dass das letzte Argument 'Charset.forName (" UTF-8 "). NewDecoder()' ist. – tchrist

+1

Eingabekodierungsfehler werden automatisch gelöscht, wenn Sie dies tun. – tchrist

+0

Es ist kein Encoder erforderlich. Der Konstruktor akzeptiert entweder einen String, einen Zeichensatz oder einen Encoder in den beiden Input/Output-Klassen. Nicht sicher, was du mit deinem Kommentar meinst. Können Sie bitte näher ausführen? –

41

Graben FileWriter und FileReader, die genau deshalb nutzlos sind, weil sie Ihnen nicht erlauben, die Kodierung anzugeben. Verwenden Sie stattdessen

new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)

und

new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);

+9

Wenn Sie nicht das sehr ausführliche 'Charset.forName (" UTF-8 "). NewDecoder()' Argument (oder irgendein schickeres Konstrukt) statt nur "UTF-8" verwenden, werden Sie nicht richtig sein Benachrichtigung über Codierungsfehler (lesen: Ausnahmen werden unterdrückt, und es wird geheimnisvoll Codierungsfehler ausblenden). – tchrist

+2

'neuer OutputStreamWriter (neuer FileOutputStream (Datei), StandardCharsets.UTF_8)' – Abdull

64

Sicher Encoding Konstrukteurs

Java Erste richtig Sie von Codierungsfehler benachrichtigen ist schwierig.Sie müssen die wortreichste verwenden und, ach, die mindestens der vier alternativen contructors verwendet für jede InputStreamReader und OutputStreamWriter eine richtige Ausnahme auf eine Codierung Glitch zu empfangen.

Für Datei-I/O, immer darauf achten, immer als das zweite Argument zu verwenden, sowohl auf OutputStreamWriter und InputStreamReader die Phantasie Encoder Argument:

Charset.forName("UTF-8").newEncoder() 

Es gibt andere auch ausgefallenere Möglichkeiten, aber keiner der drei einfachere Möglichkeiten arbeiten für die Ausnahmeübergabe. Dies tut:

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 für den Betrieb mit

$ java -Dfile.encoding=utf8 SomeTrulyRemarkablyLongcLassNameGoeShere 

Das Problem ist, dass das nicht das volle Encoder Argument Formular verwendet wird für die Zeichenströme, und so werden Sie wieder Codierung Probleme verpassen.

Längeres Beispiel

hier ein längeres Beispiel, das man einen Prozess statt eine Datei verwalten, wo wir zwei verschiedene Eingänge fördern Ströme und einen Ausgang Bytedatenstream alle auf UTF-8-Zeichenbytes Strom mit Exception Handling absichern:

// this runs a perl script with UTF-8 STD{IN,OUT,ERR} streams 
Process 
slave_process = Runtime.getRuntime().exec("perl -CS script args"); 

// fetch his stdin byte stream... 
OutputStream 
__bytes_into_his_stdin = slave_process.getOutputStream(); 

// and make a character stream with exceptions on encoding errors 
OutputStreamWriter 
    chars_into_his_stdin = new OutputStreamWriter(
          __bytes_into_his_stdin, 
     /* DO NOT OMIT! */ Charset.forName("UTF-8").newEncoder() 
         ); 

// fetch his stdout byte stream... 
InputStream 
__bytes_from_his_stdout = slave_process.getInputStream(); 

// and make a character stream with exceptions on encoding errors 
InputStreamReader 
    chars_from_his_stdout = new InputStreamReader(
          __bytes_from_his_stdout, 
     /* DO NOT OMIT! */ Charset.forName("UTF-8").newDecoder() 
         ); 

// fetch his stderr byte stream... 
InputStream 
__bytes_from_his_stderr = slave_process.getErrorStream(); 

// and make a character stream with exceptions on encoding errors 
InputStreamReader 
    chars_from_his_stderr = new InputStreamReader(
          __bytes_from_his_stderr, 
     /* DO NOT OMIT! */ Charset.forName("UTF-8").newDecoder() 
         ); 

Jetzt haben Sie drei Zeichenströme, die alle Ausnahme auf Codierungsfehler erhöhen bzw. chars_into_his_stdin, chars_from_his_stdout und chars_from_his_stderr genannt.

Das ist nur etwas komplizierter als das, was Sie für Ihr Problem brauchen, 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.

Nur nicht über mich starten PrintStream s essen Ausnahmen.

+1

Große Antwort, aber ich denke, es gibt einen kleineren Fehler damit 'InputStreamReader char_input = neuer InputStreamWriter' sollte lesen: 'InputStreamReader char_input = neuer InputStreamReader', und Der 'InputStreamReader'-Konstruktor benötigt einen' CharsetDecoder', keinen 'CharsetEncoder'. –

+0

Aber ist das ein echtes Problem, was ist nicht möglich für UTF-8 zu vertreten, ich dachte, es könnte alles kodieren. –

+0

Wenn Sie sich darüber beschweren wollen, dass Streams Ausnahmen essen, versuchen Sie 'CipherInputStream', das 'BadPaddingException's entfernt, selbst wenn sie von einem authentifizierten Cipher-Stream erstellt werden :( –

4

Mit chinesischem Text habe ich versucht, den Charset UTF-16 zu verwenden und glücklicherweise funktioniert es.

Hoffe, das könnte helfen!

PrintWriter out = new PrintWriter(file, "UTF-16"); 
-2

Meiner Meinung nach

Wenn Sie möchten, schreiben folgen Art UTF-8 .Sie ein Byte array.Then erstellen, sollten Sie wie folgt vorgehen kann: byte[] by=("<?xml version=\"1.0\" encoding=\"utf-8\"?>"+"Your string".getBytes();

Dann , Sie können 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(); 
+0

Können Sie diesem Code eine Erklärung hinzufügen? –

+0

Willkommen bei Stack Overflow! Während dieses Code-Snippet die Frage lösen kann, hilft [einschließlich einer Erklärung] (// meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) wirklich, die Qualität Ihres Posts zu verbessern. Denken Sie daran, dass Sie die Frage für Leser in der Zukunft beantworten, und diese Leute könnten die Gründe für Ihren Codevorschlag nicht kennen. Bitte versuchen Sie auch nicht, Ihren Code mit erklärenden Kommentaren zu füllen, dies reduziert die Lesbarkeit sowohl des Codes als auch der Erklärungen! –

0

Da Java 7 es eine einfache Art und Weise ist die Zeichencodierung BufferedWriter BufferedReaders und zu handhaben. Sie können einen BufferedWriter direkt erstellen, indem Sie die Files-Klasse verwenden, anstatt verschiedene Writer-Instanzen zu erstellen.Sie können einfach eine BufferedWriter erstellen, die Zeichencodierung, durch den Aufruf der Ansicht:

Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8); 

Sie können mehr über sie in JavaDoc finden:

Verwandte Themen