Os problemas de charset são confusos e complicados por si mesmos, mas, além disso, é necessário lembrar os nomes exatos dos seus charsets. É isso "utf8"
? Ou "utf-8"
? Ou talvez "UTF-8"
? Ao pesquisar exemplos de código na Internet, você verá todas as opções acima. Por que não fazê-los nomeados constantes e usar Charset.UTF8
?
java
character-encoding
serg
fonte
fonte
MessageDigest#getInstance()
a propósito.Respostas:
A resposta simples para a pergunta é que as seqüências de caracteres disponíveis variam de plataforma para plataforma.
No entanto, há seis que precisam estar presentes, portanto, constantes poderiam ter sido feitas para aquelas há muito tempo. Não sei por que não estavam.
O JDK 1.4 fez uma grande coisa ao introduzir o tipo Charset. Nesse momento, eles não desejariam mais fornecer constantes String, pois o objetivo é fazer com que todos usem instâncias de Charset. Então, por que não fornecer as seis constantes padrão do Charset? Perguntei a Martin Buchholz, já que ele estava sentado ao meu lado e ele disse que não havia um motivo realmente particularmente bom, exceto que, na época, as coisas ainda estavam pela metade - poucas APIs do JDK haviam sido adaptadas para aceitar Charset, e dos que eram, as sobrecargas de Charset geralmente tiveram um desempenho um pouco pior.
É triste que seja apenas no JDK 1.6 que eles finalmente terminaram de equipar tudo com sobrecargas no Charset. E que essa situação de desempenho reverso ainda existe (a razão pela qual é incrivelmente estranha e eu não posso explicar, mas está relacionada à segurança!).
Para encurtar a história - apenas defina suas próprias constantes ou use a classe Charsets da Guava à qual Tony the Pony se vinculou (embora essa biblioteca ainda não tenha sido realmente lançada).
Atualização: uma
StandardCharsets
classe está no JDK 7.fonte
String(byte bytes[], int offset, int length, Charset charset)
é implementado. De fato, o impacto no desempenho não é trivial ao criar uma cadeia pequena a partir de um byte grande [].Dois anos depois, o StandardCharsets do Java 7 agora define constantes para os 6 charsets padrão.
Se você está preso no Java 5/6, pode usar constantes Charsets do Guava , conforme sugerido por Kevin Bourrillion e Jon Skeet.
fonte
Eu diria que podemos fazer muito melhor do que isso ... por que os conjuntos de caracteres com garantia de disponibilidade não são acessíveis diretamente?
Charset.UTF8
deve ser uma referência aoCharset
, não ao nome como uma string. Dessa forma, não teríamos que lidar comUnsupportedEncodingException
todos os lados.Lembre-se, também acho que o .NET escolheu uma estratégia melhor por padrão em UTF-8 em todos os lugares. Em seguida, ele estragou o nome da propriedade de codificação "sistema operacional padrão" simplesmente
Encoding.Default
- o que não é o padrão no próprio .NET :(Voltando a reclamar sobre o suporte a charset do Java - por que não existe um construtor para
FileWriter
/FileReader
que leva umCharset
? Basicamente, essas são classes quase inúteis devido a essa restrição - você quase sempre precisa deInputStreamReader
cerca de aFileInputStream
ou equivalente para a saída :(Enfermeira, enfermeira - onde está meu remédio?
Edição: Ocorre-me que isso realmente não respondeu à pergunta. A resposta real é presumivelmente "ninguém envolvido pensou nisso" ou "alguém envolvido pensou que era uma má idéia". Eu sugeriria fortemente que as classes de utilidade internas que fornecem os nomes ou conjuntos de caracteres evitem duplicação em torno da base de código ... Ou você pode simplesmente usar o que usamos no Google quando esta resposta foi escrita pela primeira vez . (Observe que, a partir do Java 7, você apenas usaria
StandardCharsets
.)fonte
No Java 1.7
import java.nio.charset.StandardCharsets
ex:
StandardCharsets.UTF_8
StandardCharsets.US_ASCII
fonte
O estado atual da API de codificação deixa algo a desejar. Algumas partes da API Java 6 não aceito
Charset
no lugar de um string (emlogging
,dom.ls
,PrintStream
, pode haver outros). Não ajuda que as codificações devam ter nomes canônicos diferentes para diferentes partes da biblioteca padrão.Eu posso entender como as coisas chegaram onde estão; Não tenho certeza se tenho idéias brilhantes sobre como corrigi-las.
Como um aparte ...
Você pode procurar os nomes para a implementação Java 6 da Sun aqui .
Para UTF-8, os valores canônicos são
"UTF-8"
parajava.nio
e"UTF8"
parajava.lang
ejava.io
. As únicas codificações exigidas por uma especificação para o JRE são: US-ASCII; ISO-8859-1; UTF-8; UTF-16BE; UTF-16LE; UTF-16 .fonte
Há muito tempo, defini uma classe de utilitário com constantes UTF_8, ISO_8859_1 e US_ASCII Charset.
Além disso, alguns há muito tempo (2+ anos) eu fiz um teste de desempenho simples entre
new String( byte[], Charset )
enew String( byte[], String charset_name )
e descobriu que esta implementação é CONSIDERAVELMENTE mais rápido. Se você der uma olhada no código fonte, verá que eles realmente seguem um caminho bem diferente.Por esse motivo, incluí um utilitário na mesma classe
Por que o construtor String (byte [], Charset) não faz o mesmo, me bate.
fonte
Charset
precisa ser registrado, para que a exceção possa acontecer. IIRC, houve algumas alterações no JDK7 para torná-lo mais rápido paraCharset
implementações em bom estado (eliminar a cópia extra).