2012-03-24 12 views
61

Ho tuttavia il seguente codice, voglio che scriva come un file UTF-8 per gestire i caratteri stranieri. C'è un modo per farlo, c'è bisogno di avere un parametro?Scrivere un file in UTF-8 usando FileWriter (Java)?

Apprezzerei molto il vostro aiuto. Grazie.

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(); 
} 

risposta

42

è necessario utilizzare la classe OutputStreamWriter come parametro scrittore per il vostro BufferedWriter. Accetta una codifica. Recensione javadocs per questo.

Un po 'come questo:

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

Oppure si può impostare la codifica del sistema corrente con la proprietà di sistema file.encoding a UTF-8.

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

Si può anche impostare come una proprietà di sistema in fase di esecuzione con System.setProperty(...) se è necessario solo per questo file specifico, ma in un caso come questo penso io preferirei il OutputStreamWriter.

Impostando la proprietà di sistema è possibile utilizzare FileWriter e prevedere che utilizzerà UTF-8 come codifica predefinita per i file. In questo caso per tutti i file che leggi e scrivi.

EDIT

  • A partire da API 19, è possibile sostituire la stringa "UTF-8" con StandardCharsets.UTF_8

  • Come suggerito nei commenti qui sotto per tchrist, se avete intenzione di rilevare errori di codifica nel tuo file dovresti essere forzato ad usare l'approccio OutputStreamWriter e utilizzare il costruttore che riceve un codificatore di caratteri.

    Un po 'come

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

    Si può scegliere tra le azioni IGNORE | REPLACE | REPORT

Inoltre, questa questione è stata già una risposta here.

+0

Questo non è sufficiente . È necessario anche un 'InputStreamReader (InputStream in, CharsetDecoder dec)', tale che l'ultimo argomento sia 'Charset.forName (" UTF-8 "). NewDecoder()'. – tchrist

+1

Gli errori di codifica degli input verranno silenziati automaticamente se lo fai. – tchrist

+0

Non è necessario un encoder. Il costruttore accetta una stringa, un set di caratteri o un codificatore in entrambe le classi di input/output. Non sei sicuro di cosa intendi con il tuo commento. Puoi elaborare, per favore? –

41

Ditch FileWriter e FileReader, che sono inutili esattamente perché non consentono di specificare la codifica. Invece, utilizzare

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

e

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

+9

Se non si utilizza l'argomento molto dettagliato 'Charset.forName (" UTF-8 "). NewDecoder()' (o qualche costrutto fancier) invece di solo "UTF-8" ', non si andrà bene notificato degli errori di codifica (leggi: le eccezioni saranno soppresse e nasconderà misteriosamente errori di codifica). – tchrist

+2

'new OutputStreamWriter (nuovo FileOutputStream (file), StandardCharsets.UTF_8)' – Abdull

64

sicuro di codifica Costruttori

Ottenere Java per notificare correttamente di errori di codifica è difficile.È necessario utilizzare il più dettagliato e, purtroppo, la meno utilizzato delle quattro Case costruttrici di alternative per ciascuna delle InputStreamReader e OutputStreamWriter ricevere un'eccezione appropriata su un difetto di codifica.

Per file di I/O, sempre assicurarsi di utilizzare sempre come secondo argomento sia OutputStreamWriter e InputStreamReader l'argomento encoder fantasia:

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

Ci sono altre possibilità ancora più elaborate, ma nessuno dei tre più semplice le possibilità funzionano per le eccezioni. Questi fanno:

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

Per quanto riguarda la corsa con

$ java -Dfile.encoding=utf8 SomeTrulyRemarkablyLongcLassNameGoeShere 

Il problema è che che non utilizzerà il modulo encoder argomento completa per i flussi del personaggio, e così si sarà nuovamente perdere problemi di codifica.

Longer Esempio

Ecco un esempio più, questa gestire un processo invece di un file, dove promuoviamo due ingressi diversi byte flussi ed una corrente di uscita di byte tutto UTF-8 caratteri flussi con la gestione completa eccezioni:

// 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() 
         ); 

Ora avete tre carattere flussi che tutti sollevano un'eccezione in caso di errori di codifica, rispettivamente chiamati chars_into_his_stdin, chars_from_his_stdout, e chars_from_his_stderr.

Questo è solo leggermente più complicato di quello che ti serve per il tuo problema, la cui soluzione ho dato nella prima metà di questa risposta. Il punto chiave è questo è l'unico modo per rilevare errori di codifica.

Basta non farmi iniziare a proposito di PrintStream s eccezioni alimentari.

+1

Ottima risposta, ma penso che ci sia un piccolo problema con esso -InputStreamReader char_input = new InputStreamWriter' dovrebbe contenere: 'InputStreamReader char_input = new InputStreamReader', e il costruttore 'InputStreamReader' prende un' CharsetDecoder', non un 'CharsetEncoder'. –

+0

Ma questo è un problema reale, ciò che non è possibile rappresentare per UTF-8, ho pensato che potesse codificare qualsiasi cosa. –

+0

Se vuoi lamentarti degli Stream che mangiano eccezioni, prova "CipherInputStream', che rimuove' BadPaddingException', anche se sono creati da un flusso di crittografia autenticato :( –

4

Con testo cinese, ho provato a utilizzare il set di caratteri UTF-16 e fortunatamente funziona.

Spero che questo possa aiutare!

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

A mio parere

seguire se si vuole scrivere tipo UTF-8 .È dovrebbe creare un byte array.Then, si può fare come il seguente: byte[] by=("<?xml version=\"1.0\" encoding=\"utf-8\"?>"+"Your string".getBytes();

Poi , puoi scrivere ogni byte nel file che hai creato. Esempio:

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

Potresti aggiungere qualche spiegazione a questo codice? –

+0

Benvenuti in Stack Overflow! Anche se questo snippet di codice può risolvere la domanda, [inclusa una spiegazione] (// meta.stackexchange.com/questions/114762/explaining-entely-code-based-answers) aiuta davvero a migliorare la qualità del tuo post. Ricorda che stai rispondendo alla domanda per i lettori in futuro, e queste persone potrebbero non conoscere le ragioni del tuo suggerimento sul codice. Cerca anche di non affollare il tuo codice con commenti esplicativi, questo riduce la leggibilità sia del codice che delle spiegazioni! –

0

Poiché Java 7 v'è un modo semplice per gestire carattere codifica BufferedWriter e BufferedReaders. È possibile creare un BufferedWriter direttamente utilizzando la classe File invece di creare varie istanze di Writer.Si può semplicemente creare un BufferedWriter, che considera la codifica dei caratteri, chiamando:

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

È possibile trovare maggiori su di esso in JavaDoc:

Problemi correlati