java - validar - ver codificacion sublime
AplicaciĆ³n Java: no se puede leer el archivo codificado iso-8859-1 correctamente (5)
Tengo un archivo codificado como iso-8859-1 y contiene caracteres como ô.
Estoy leyendo este archivo con código Java, algo así como:
File in = new File("myfile.csv");
InputStream fr = new FileInputStream(in);
byte[] buffer = new byte[4096];
while (true) {
int byteCount = fr.read(buffer, 0, buffer.length);
if (byteCount <= 0) {
break;
}
String s = new String(buffer, 0, byteCount,"ISO-8859-1");
System.out.println(s);
}
Sin embargo, el carácter ô siempre está distorsionado, por lo general se imprime como una? .
He leído sobre el tema (y aprendí un poco en el camino), por ejemplo
- http://www.joelonsoftware.com/articles/Unicode.html
- http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
- http://www.ingrid.org/java/i18n/utf-16/
pero todavía no puedo hacer que esto funcione
Curiosamente, esto funciona en mi pc local (xp) pero no en mi linux box.
He comprobado que mi jdk admite los conjuntos de caracteres necesarios (son estándar, por lo que no es una sorpresa) con:
System.out.println(java.nio.charset.Charset.availableCharsets());
Básicamente, si funciona en su PC XP local pero no en Linux, y está analizando el mismo archivo (es decir, lo transfirió de forma binaria entre los cuadros), probablemente tenga algo que ver con System.out. Llamada impresa. No sé cómo verificar la salida, pero si lo haces conectándose con un shell remoto desde el cuadro de XP, entonces hay que considerar el conjunto de caracteres del shell (y del cliente).
Además, lo que sugiere Zach Scrivena también es cierto, no se puede suponer que se pueden crear cadenas a partir de fragmentos de datos de esa manera: use un InputStreamReader o lea los datos completos en una matriz primero (obviamente no va a funcionar para un archivo grande) . Sin embargo, dado que parece funcionar en XP, me atrevería a suponer que probablemente este no sea su problema en este caso específico.
Si puede, intente ejecutar su programa en el depurador para ver qué hay dentro de su cadena ''s'' después de que se haya creado. Es posible que tenga contenido correcto, pero la salida se distorsiona después de la llamada a System.out.println (s). En ese caso, probablemente exista una discrepancia entre lo que Java piensa que es la codificación de su salida y la codificación de caracteres de su terminal / consola en Linux.
Sospecho que su archivo no está realmente codificado como ISO-8859-1, o System.out no sabe cómo imprimir el carácter.
Recomiendo que para comprobar el primero, examine el byte relevante en el archivo. Para verificar el segundo, examine el carácter relevante en la cadena, imprimiéndolo con
System.out.println((int) s.getCharAt(index));
En ambos casos, el resultado debería ser 244 decimal; 0xf4 hex.
Vea mi artículo sobre la eliminación de errores Unicode para obtener consejos generales (el código presentado está en C #, pero es fácil de convertir a Java, y los principios son los mismos).
En general, por cierto, envolvería la transmisión con un InputStreamReader
con la codificación correcta; es más fácil que crear nuevas cadenas "a mano". Me doy cuenta de que esto puede ser solo un código de demostración.
EDITAR: Aquí hay una manera realmente fácil de probar si la consola funcionará o no:
System.out.println("Here''s the character: /u00f4");
@Joel: su propia respuesta confirma que el problema es una diferencia entre la codificación predeterminada en su sistema operativo (UTF-8, la que Java ha recogido) y la codificación que está usando su terminal (ISO-8859-1).
Considera este código:
public static void main(String[] args) throws IOException {
byte[] data = { (byte) 0xF4 };
String decoded = new String(data, "ISO-8859-1");
if (!"/u00f4".equals(decoded)) {
throw new IllegalStateException();
}
// write default charset
System.out.println(Charset.defaultCharset());
// dump bytes to stdout
System.out.write(data);
// will encode to default charset when converting to bytes
System.out.println(decoded);
}
Por defecto, mi terminal Ubuntu (8.04) usa la codificación UTF-8. Con esta codificación, esto se imprime:
UTF-8
? ô
Si cambio la codificación del terminal a ISO 8859-1, esto se imprime:
UTF-8
ô
En ambos casos, los mismos bytes están siendo emitidos por el programa Java:
5554 462d 380a f4c3 b40a
La única diferencia está en cómo el terminal está interpretando los bytes que recibe. En ISO 8859-1, ô está codificado como 0xF4. En UTF-8, ô se codifica como 0xC3B4. Los otros caracteres son comunes a ambas codificaciones.
Analizar el archivo como bloques de bytes de tamaño fijo no es bueno, ¿y si algún personaje tiene una representación de bytes que se extiende a través de dos bloques? Use un InputStreamReader
con la codificación de caracteres apropiada en su lugar:
BufferedReader br = new BufferedReader(
new InputStreamReader(
new FileInputStream("myfile.csv"), "ISO-8859-1");
char[] buffer = new char[4096]; // character (not byte) buffer
while (true)
{
int charCount = br.read(buffer, 0, buffer.length);
if (charCount == -1) break; // reached end-of-stream
String s = String.valueOf(buffer, 0, charCount);
// alternatively, we can append to a StringBuilder
System.out.println(s);
}
Por cierto, recuerde comprobar que el carácter Unicode puede mostrarse correctamente. También puede redirigir la salida del programa a un archivo y luego compararlo con el archivo original.
Como sugiere Jon Skeet , el problema también puede estar relacionado con la consola. Pruebe System.console().printf(s)
para ver si hay alguna diferencia.