2012-03-24 260 views
61

Tengo el siguiente código, sin embargo, quiero que escriba como un archivo UTF-8 para manejar caracteres extraños. ¿Hay alguna forma de hacerlo? ¿Hay alguna necesidad de tener un parámetro?¿Escribir un archivo en UTF-8 usando FileWriter (Java)?

Realmente agradecería su ayuda con esto. Gracias.

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

Respuesta

42

Es necesario utilizar la clase OutputStreamWriter como parámetro escritor para su BufferedWriter. Acepta una codificación. Revise javadocs para ello.

Algo como esto:

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

O puede establecer la codificación del sistema actual con la propiedad del sistema file.encoding a UTF-8.

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

También puede configurarlo como una propiedad del sistema en tiempo de ejecución con System.setProperty(...) si solamente se necesita para este archivo específico, pero en un caso como este creo que preferiría el OutputStreamWriter.

Al establecer la propiedad del sistema, puede usar FileWriter y esperar que use UTF-8 como la codificación predeterminada para sus archivos. En este caso, para todos los archivos que lee y escribe.

EDITAR

  • A partir de API 19, puede reemplazar la cadena "UTF-8" con StandardCharsets.UTF_8

  • Como se sugiere en los comentarios a continuación por tchrist, si tiene la intención de detectar Al codificar errores en su archivo, se verá forzado a utilizar el enfoque OutputStreamWriter y utilizar el constructor que recibe un codificador de juegos de caracteres.

    Algo así como

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

    Usted puede elegir entre las acciones IGNORE | REPLACE | REPORT

Además, esta cuestión ya fue respondida here.

+0

Eso no es suficiente . También necesita un 'InputStreamReader (InputStream in, CharsetDecoder dec)', de modo que el último argumento sea 'Charset.forName (" UTF-8 "). NewDecoder()'. – tchrist

+1

Los errores de codificación de entrada se eliminarán silenciosamente si lo hace así. – tchrist

+0

No hay necesidad de un codificador. El constructor acepta una Cadena, un Juego de Caracteres o un Codificador en las clases de Entrada/Salida. No estoy seguro de lo que quieres decir con tu comentario. ¿Puedes elaborar, por favor? –

41

Ditch FileWriter y FileReader, que son inútiles porque no permiten especificar la codificación. En su lugar, utilice

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

y

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

+9

Si no utiliza el muy detallado 'Charset.forName (" UTF-8 "). NewDecoder()' argumento (o alguna construcción más elegante) en lugar de simplemente '" UTF-8 "', no estará correctamente notificado de errores de codificación (léase: las excepciones serán suprimidas, y ocultará misteriosamente los errores de codificación). – tchrist

+2

'nuevo OutputStreamWriter (nuevo FileOutputStream (archivo), StandardCharsets.UTF_8)' – Abdull

64

seguras de codificación de constructores

Obtención de Java para notificarle adecuadamente de errores de codificación es complicado.Debe utilizar el más detallado y, por desgracia, la menos utilizado de los cuatro contructors alternos para cada uno de InputStreamReader y OutputStreamWriter a recibir una excepción adecuada en una codificación fallo.

Para archivo de E/S, siempre asegúrese de utilizar siempre el segundo argumento de tanto OutputStreamWriter y InputStreamReader el argumento codificador de lujo:

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

Hay otras posibilidades, incluso más elegante, pero ninguno de los tres más sencillo las posibilidades funcionan para la entrega de excepciones. Estos hacen:

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

En cuanto a correr con

$ java -Dfile.encoding=utf8 SomeTrulyRemarkablyLongcLassNameGoeShere 

El problema es que eso no va a utilizar la forma completa argumento codificador para el personaje arroyos, y por lo que volverá a perderse problemas de codificación.

más largo Ejemplo

He aquí un ejemplo más, éste la gestión de un proceso en lugar de un archivo, donde se promueve dos entradas diferentes bytes de arroyos y un flujo de bytes de salida todo a UTF-8 streams de caracteres con el manejo de excepciones completa:

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

Ahora usted tiene tres streams de caracteres que todos aumentan excepción de errores de codificación, respectivamente llamados chars_into_his_stdin, chars_from_his_stdout, y chars_from_his_stderr.

Esto es solo un poco más complicado que lo que necesita para su problema, cuya solución di en la primera mitad de esta respuesta. El punto clave es que esta es la única forma de detectar errores de codificación.

Simplemente no me digas acerca de PrintStream s comiendo excepciones.

+1

Gran respuesta, pero creo que hay un error menor con él -'InputStreamReader char_input = new InputStreamWriter' debería leer: 'InputStreamReader char_input = new InputStreamReader', y el constructor 'InputStreamReader' toma' CharsetDecoder', no 'CharsetEncoder'. –

+0

Pero, ¿es esto un problema real? Lo que no es posible representar para UTF-8, pensé que podría codificar cualquier cosa. –

+0

Si desea quejarse de las excepciones de Streaming eating, intente 'CipherInputStream', que elimina' BadPaddingException''s, incluso si son creadas por una secuencia de cifrado autenticada :( –

4

Con el texto en chino, traté de usar el Charset UTF-16 y afortunadamente funcionó.

Espero que esto ayude!

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

En mi opinión

Si quieres escribir siguen tipo UTF-8 .you de crear un byte array.Then, se puede hacer, como la siguiente: byte[] by=("<?xml version=\"1.0\" encoding=\"utf-8\"?>"+"Your string".getBytes();

Entonces , puedes escribir cada byte en el archivo que creaste. Ejemplo:

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

¿Podría agregar alguna explicación a este código? –

+0

¡Bienvenido a Stack Overflow! Si bien este fragmento de código puede resolver la pregunta, [incluyendo una explicación] (// meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) realmente ayuda a mejorar la calidad de su publicación. Recuerde que usted está respondiendo la pregunta a los lectores en el futuro, y es posible que esas personas no sepan los motivos de su sugerencia de código. Por favor, intente no saturar su código con comentarios explicativos, ¡esto reduce la legibilidad tanto del código como de las explicaciones! –

0

Desde Java 7 hay una manera más fácil de manejar la codificación de caracteres de BufferedWriter y BufferedReaders. Puede crear un BufferedWriter directamente utilizando la clase Files en lugar de crear varias instancias de Writer.Usted puede simplemente crear un BufferedWriter, que considera la codificación de caracteres, llamando al:

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

Puede encontrar más información sobre ella en JavaDoc:

Cuestiones relacionadas