uso titledborder poner definicion borde java encoding character-encoding

poner - titledborder java



¿Cómo encontrar el juego de caracteres/codificación predeterminado en Java? (6)

La respuesta obvia es usar Charset.defaultCharset() pero recientemente descubrimos que esta podría no ser la respuesta correcta. Me dijeron que el resultado es diferente del juego de caracteres real predeterminado utilizado por las clases de java.io en varias ocasiones. Parece que Java tiene 2 juegos de juego de caracteres predeterminado. ¿Alguien tiene alguna idea sobre este tema?

Pudimos reproducir un caso fallido. Es un tipo de error del usuario, pero aún puede exponer la causa raíz de todos los demás problemas. Aquí está el código,

public class CharSetTest { public static void main(String[] args) { System.out.println("Default Charset=" + Charset.defaultCharset()); System.setProperty("file.encoding", "Latin-1"); System.out.println("file.encoding=" + System.getProperty("file.encoding")); System.out.println("Default Charset=" + Charset.defaultCharset()); System.out.println("Default Charset in Use=" + getDefaultCharSet()); } private static String getDefaultCharSet() { OutputStreamWriter writer = new OutputStreamWriter(new ByteArrayOutputStream()); String enc = writer.getEncoding(); return enc; } }

Nuestro servidor requiere juego de caracteres predeterminado en Latin-1 para tratar con una codificación mixta (ANSI / Latin-1 / UTF-8) en un protocolo heredado. Entonces todos nuestros servidores se ejecutan con este parámetro de JVM,

-Dfile.encoding=ISO-8859-1

Aquí está el resultado en Java 5,

Default Charset=ISO-8859-1 file.encoding=Latin-1 Default Charset=UTF-8 Default Charset in Use=ISO8859_1

Alguien intenta cambiar el tiempo de ejecución de codificación configurando file.encoding en el código. Todos sabemos que eso no funciona. Sin embargo, esto aparentemente arroja defaultCharset () pero no afecta el juego de caracteres real predeterminado utilizado por OutputStreamWriter.

¿Es esto un error o una característica?

EDITAR: la respuesta aceptada muestra la causa raíz del problema. Básicamente, no puede confiar en defaultCharset () en Java 5, que no es la codificación predeterminada utilizada por las clases de E / S. Parece que Java 6 corrige este problema.


¿Es esto un error o una característica?

Parece un comportamiento indefinido. Sé que, en la práctica, puedes cambiar la codificación predeterminada usando una propiedad de línea de comandos, pero no creo que lo que sucede cuando lo haces está definido.

Error ID: 4153515 en problemas al establecer esta propiedad:

Esto no es un error. La especificación de la plataforma J2SE no requiere la propiedad "file.encoding"; es un detalle interno de las implementaciones de Sun y no debe ser examinado o modificado por el código de usuario. También está destinado a ser de solo lectura; es técnicamente imposible admitir la configuración de esta propiedad a valores arbitrarios en la línea de comandos o en cualquier otro momento durante la ejecución del programa.

La forma preferida de cambiar la codificación predeterminada utilizada por la VM y el sistema de tiempo de ejecución es cambiar la configuración regional de la plataforma subyacente antes de iniciar su programa Java.

Me estremezco cuando veo a personas configurando la codificación en la línea de comando: no sabes qué código va a afectar.

Si no desea utilizar la codificación predeterminada, establezca la codificación que desea explícitamente a través del método / constructor apropiado.


El comportamiento no es realmente tan extraño. En cuanto a la implementación de las clases, es causado por:

  • Charset.defaultCharset () no almacena en caché el conjunto de caracteres determinado en Java 5.
  • Establecer la propiedad del sistema "file.encoding" e invocar Charset.defaultCharset () nuevamente causa una segunda evaluación de la propiedad del sistema, no se encuentra ningún juego de caracteres con el nombre "Latin-1", por lo que Charset.defaultCharset se predetermina a "UTF-8 ".
  • Sin embargo, OutputStreamWriter almacena en caché el juego de caracteres predeterminado y probablemente ya se usa durante la inicialización de VM, por lo que su juego de caracteres predeterminado se desvía de Charset.defaultCharset () si la propiedad del sistema "file.encoding" se ha modificado en tiempo de ejecución.

Como ya se señaló, no está documentado cómo debe comportarse la máquina virtual en tal situación. La documentación de la API Charset.defaultCharset () no es muy precisa sobre cómo se determina el conjunto de caracteres predeterminado, solo menciona que generalmente se realiza en el inicio de VM, en función de factores como el conjunto de caracteres predeterminado del sistema operativo o la configuración regional predeterminada.


Establecí el argumento vm en el servidor WAS como -Dfile.encoding = UTF-8 para cambiar el conjunto de caracteres predeterminado de los servidores.


Esto es realmente extraño ... Una vez establecido, el Charset predeterminado se almacena en caché y no se cambia mientras la clase está en la memoria. Estableciendo la propiedad "file.encoding" con System.setProperty("file.encoding", "Latin-1"); no hace nada. Cada vez que se llama a Charset.defaultCharset() devuelve el juego de caracteres en caché.

Aquí están mis resultados:

Default Charset=ISO-8859-1 file.encoding=Latin-1 Default Charset=ISO-8859-1 Default Charset in Use=ISO8859_1

Aunque estoy usando JVM 1.6.

(actualizar)

De acuerdo. Reproduje tu error con JVM 1.5.

Al observar el código fuente de 1.5, el juego de caracteres predeterminado en caché no se está configurando. No sé si esto es un error o no, pero 1.6 cambia esta implementación y usa el juego de caracteres en caché:

JVM 1.5:

public static Charset defaultCharset() { synchronized (Charset.class) { if (defaultCharset == null) { java.security.PrivilegedAction pa = new GetPropertyAction("file.encoding"); String csn = (String)AccessController.doPrivileged(pa); Charset cs = lookup(csn); if (cs != null) return cs; return forName("UTF-8"); } return defaultCharset; } }

JVM 1.6:

public static Charset defaultCharset() { if (defaultCharset == null) { synchronized (Charset.class) { java.security.PrivilegedAction pa = new GetPropertyAction("file.encoding"); String csn = (String)AccessController.doPrivileged(pa); Charset cs = lookup(csn); if (cs != null) defaultCharset = cs; else defaultCharset = forName("UTF-8"); } } return defaultCharset; }

Cuando establece la codificación del archivo en file.encoding=Latin-1 la próxima vez que llama a Charset.defaultCharset() , lo que ocurre es que, debido a que el conjunto de caracteres predeterminado en caché no está configurado, intentará encontrar el juego de caracteres apropiado para el nombre Latin-1 . Este nombre no se encuentra porque es incorrecto y devuelve el UTF-8 predeterminado.

En cuanto a por qué las clases IO como OutputStreamWriter devuelven un resultado inesperado,
la implementación de sun.nio.cs.StreamEncoder (que las clases de IO utilizan) es diferente también para JVM 1.5 y JVM 1.6. La implementación de JVM 1.6 se basa en el método Charset.defaultCharset() para obtener la codificación predeterminada, si no se proporciona una a las clases IO. La implementación de JVM 1.5 usa un método diferente Converters.getDefaultEncodingName(); para obtener el juego de caracteres predeterminado Este método usa su propio caché del conjunto de caracteres predeterminado que se establece en la inicialización de JVM:

JVM 1.6:

public static StreamEncoder forOutputStreamWriter(OutputStream out, Object lock, String charsetName) throws UnsupportedEncodingException { String csn = charsetName; if (csn == null) csn = Charset.defaultCharset().name(); try { if (Charset.isSupported(csn)) return new StreamEncoder(out, lock, Charset.forName(csn)); } catch (IllegalCharsetNameException x) { } throw new UnsupportedEncodingException (csn); }

JVM 1.5:

public static StreamEncoder forOutputStreamWriter(OutputStream out, Object lock, String charsetName) throws UnsupportedEncodingException { String csn = charsetName; if (csn == null) csn = Converters.getDefaultEncodingName(); if (!Converters.isCached(Converters.CHAR_TO_BYTE, csn)) { try { if (Charset.isSupported(csn)) return new CharsetSE(out, lock, Charset.forName(csn)); } catch (IllegalCharsetNameException x) { } } return new ConverterSE(out, lock, csn); }

Pero estoy de acuerdo con los comentarios. No deberías confiar en esta propiedad . Es un detalle de implementación.


Primero, Latin-1 es lo mismo que ISO-8859-1, por lo tanto, el valor predeterminado ya estaba bien para usted. ¿Derecha?

Estableció correctamente la codificación en ISO-8859-1 con su parámetro de línea de comando. También lo configura programáticamente en "Latin-1", pero ese no es un valor reconocido de una codificación de archivo para Java. Ver http://java.sun.com/javase/6/docs/technotes/guides/intl/encoding.doc.html

Cuando haces eso, parece que Charset se restablece a UTF-8, al mirar la fuente. Eso al menos explica la mayor parte del comportamiento.

No sé por qué OutputStreamWriter muestra ISO8859_1. Delega a clases de fuente cerrada sun.misc. *. Supongo que no se trata de la codificación por el mismo mecanismo, lo cual es extraño.

Pero, por supuesto, siempre deberías especificar qué codificación quieres decir en este código. Nunca confiaría en la plataforma predeterminada.


comprobar

System.getProperty("sun.jnu.encoding")

parece ser la misma codificación que la utilizada en la línea de comando de su sistema.