Los problemas de juego de caracteres son confusos y complicados por sí mismos, pero además de eso, debe recordar los nombres exactos de sus juegos de caracteres. Es "utf8"
? O "utf-8"
? O tal vez "UTF-8"
? Al buscar ejemplos de código en Internet, verá todo lo anterior. ¿Por qué no simplemente hacer que sean constantes con nombre y uso Charset.UTF8
?
java
character-encoding
serg
fuente
fuente
MessageDigest#getInstance()
por cierto.Respuestas:
La respuesta simple a la pregunta es que las cadenas de caracteres disponibles varían de una plataforma a otra.
Sin embargo, hay seis que deben estar presentes, por lo que se podrían haber hecho constantes para aquellos hace mucho tiempo. No sé por qué no lo fueron.
JDK 1.4 hizo una gran cosa al introducir el tipo Charset. En este punto, ya no habrían querido proporcionar constantes de cadena, ya que el objetivo es hacer que todos usen instancias de Charset. Entonces, ¿por qué no proporcionar las seis constantes Charset estándar? Le pregunté a Martin Buchholz porque estaba sentado a mi lado, y dijo que no había una razón realmente especial, excepto que en ese momento, las cosas todavía estaban a medias: muy pocas API JDK habían sido adaptadas para aceptar Charset, y de los que eran, las sobrecargas de Charset generalmente tuvieron un rendimiento ligeramente peor.
Es triste que solo sea en JDK 1.6 que finalmente terminaron de equipar todo con sobrecargas de Charset. Y que esta situación de rendimiento hacia atrás todavía existe (la razón por la cual es increíblemente extraña y no puedo explicarlo, ¡pero está relacionada con la seguridad!).
Larga historia corta: solo defina sus propias constantes o use la clase Charsets de Guava a la que Tony the Pony se vinculó (aunque esa biblioteca aún no se ha lanzado realmente).
Actualización: una
StandardCharsets
clase está en JDK 7.fuente
String(byte bytes[], int offset, int length, Charset charset)
se implementa. De hecho, el impacto en el rendimiento no es trivial cuando se crea una cadena pequeña a partir de un byte grande [].Dos años después, y StandardCharsets de Java 7 ahora define constantes para los 6 charsets estándar.
Si está atascado en Java 5/6, puede usar las constantes Charsets de Guava , como lo sugieren Kevin Bourrillion y Jon Skeet.
fuente
Yo diría que podemos hacerlo mucho mejor que eso ... ¿por qué no se puede acceder directamente a los charsets garantizados?
Charset.UTF8
debería ser una referencia alCharset
, no el nombre como una cadena. De esa manera no tendríamos que manejarUnsupportedEncodingException
todo el lugar.Eso sí, también creo que .NET eligió una mejor estrategia al usar UTF-8 en todas partes. Luego se arruinó al nombrar la propiedad de codificación "predeterminado del sistema operativo" simplemente
Encoding.Default
, que no es el valor predeterminado dentro de .NET :(Volviendo a despotricar sobre el soporte de juegos de caracteres de Java: ¿por qué no hay un constructor para
FileWriter
/FileReader
que toma unCharset
? Básicamente, esas son clases casi inútiles debido a esa restricción: casi siempre necesita unInputStreamReader
alrededor deFileInputStream
o el equivalente para la salida :(Enfermera, enfermera, ¿dónde está mi medicina?
EDITAR: Se me ocurre que esto realmente no ha respondido la pregunta. La respuesta real es, presumiblemente, "nadie involucrado lo pensó" o "alguien involucrado pensó que era una mala idea". Sugeriría encarecidamente que las clases de utilidad internas que proporcionan los nombres o conjuntos de caracteres eviten la duplicación alrededor de la base de código ... O simplemente podría usar la que usamos en Google cuando se escribió por primera vez esta respuesta . (Tenga en cuenta que a partir de Java 7, solo usaría
StandardCharsets
en su lugar).fuente
En Java 1.7
import java.nio.charset.StandardCharsets
ex:
StandardCharsets.UTF_8
StandardCharsets.US_ASCII
fuente
El estado actual de la API de codificación deja algo que desear. Algunas partes de la API de Java 6 no aceptan
Charset
en lugar de una cadena (enlogging
,dom.ls
,PrintStream
, puede haber otros). No ayuda que se supone que las codificaciones tienen diferentes nombres canónicos para diferentes partes de la biblioteca estándar.Puedo entender cómo llegaron las cosas a donde están; No estoy seguro de tener alguna idea brillante sobre cómo solucionarlos.
Como un aparte...
Puede buscar los nombres de la implementación Java 6 de Sun aquí .
Para UTF-8, los valores canónicos son
"UTF-8"
parajava.nio
y"UTF8"
parajava.lang
yjava.io
. Las únicas codificaciones que la especificación requiere un JRE para admitir son: US-ASCII; ISO-8859-1; UTF-8; UTF-16BE; UTF-16LE; UTF-16 .fuente
Hace mucho tiempo definí una clase de utilidad con las constantes UTF_8, ISO_8859_1 y US_ASCII Charset.
También, hace algún tiempo (2+ años) me hizo un simple análisis de rendimiento entre
new String( byte[], Charset )
ynew String( byte[], String charset_name )
y descubrió que esta última aplicación es CONSIDERABLEMENTE más rápido. Si observa el código fuente debajo del capó, verá que de hecho siguen un camino bastante diferente.Por esa razón, incluí una utilidad en la misma clase
Por qué el constructor String (byte [], Charset) no hace lo mismo, me gana.
fuente
Charset
necesidad no debe registrarse, por lo que la excepción puede suceder. IIRC, hubo algunos cambios en JDK7 para hacerlo más rápido paraCharset
implementaciones bien conocidas (eliminar la copia adicional).