Codificar String para UTF-8

190

Eu tenho uma String com um caractere "ñ" e tenho alguns problemas com ela. Eu preciso codificar essa String para codificação UTF-8. Eu tentei dessa maneira, mas não funciona:

byte ptext[] = myString.getBytes();
String value = new String(ptext, "UTF-8");

Como codifico essa string para utf-8?

Alex
fonte
2
Não está claro o que exatamente você está tentando fazer. O myString contém corretamente o caractere ñ e você tem problemas para convertê-lo em uma matriz de bytes (nesse caso, veja as respostas de Peter e Amir) ou o myString está corrompido e você está tentando corrigi-lo (nesse caso, veja as respostas de Joachim e eu)?
22611 Michael Borgwardt
Preciso enviar myString para um servidor com codificação utf-8 e preciso converter o caractere "ñ" para codificação utf-8.
20911 Alex
1
Bem, se esse servidor espera UTF-8, o que você precisa enviar é bytes, não uma String. Portanto, conforme a resposta de Peter, especifique a codificação na primeira linha e solte a segunda linha.
precisa
@ Michael: Eu concordo que não está claro qual é a verdadeira intenção aqui. Parece haver muitas perguntas em que as pessoas estão tentando fazer conversões explícitas entre Strings e bytes, em vez de deixarem {In,Out}putStream{Read,Writ}ersfazer isso por elas. Eu quero saber porque?
precisa saber é o seguinte
1
@ Michael: Obrigado, acho que faz sentido. Mas também torna mais difícil do que precisa ser, não é? Não gosto muito de idiomas que funcionam dessa maneira e, portanto, tente evitar trabalhar com eles. Eu acho que o modelo de Java de Strings de caracteres em vez de bytes facilita muito as coisas. Perl e Python também compartilham o modelo "tudo é strings Unicode". Sim, nos três, você ainda pode obter bytes se trabalhar nisso, mas, na prática, parece raro o que você realmente precisa: é um nível bastante baixo. Além disso, é como escovar um gato na direção errada, se é que você me entende. :)
tchrist

Respostas:

140

String objetos em Java usam a codificação UTF-16 que não pode ser modificada.

A única coisa que pode ter uma codificação diferente é a byte[]. Portanto, se você precisar de dados UTF-8, precisará de um byte[]. Se você possui um Stringque contém dados inesperados, o problema está em um local anterior que converteu incorretamente alguns dados binários em um String(ou seja, estava usando a codificação incorreta).

Joachim Sauer
fonte
92
Tecnicamente falando, o byte [] não possui nenhuma codificação. A codificação PLUS do array de bytes pode fornecer uma string.
Peter Štibraný
1
@ Peter: verdadeiro. Mas anexar uma codificação apenas faz sentido byte[], mas não faz sentido String(a menos que a codificação seja UTF-16; nesse caso, faz sentido, mas ainda assim informações desnecessárias).
Joachim Sauer
4
String objects in Java use the UTF-16 encoding that can't be modified. Você tem uma fonte oficial para esta cotação?
Ahmad Hajjar 25/10
@AhmadHajjar docs.oracle.com/javase/10/docs/api/java/lang/… : "A plataforma Java usa a representação UTF-16 em matrizes de caracteres e nas classes String e StringBuffer."
precisa
173

Que tal usar

ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(myString)
Amir Rachum
fonte
Veja minha discussão com Peter. Mas se a suposição dele sobre a questão estiver correta, sua solução ainda não seria uma ideia, pois retorna um ByteBuffer.
precisa
8
Mas como obtenho uma String codificada? ele retorna um ByteBuffer
Alex
7
@ Alex: não é possível ter uma String Java codificada em UTF-8. Você quer bytes, por isso ou usar o ByteBuffer diretamente (poderia mesmo ser a melhor solução, se o seu objetivo é enviá-lo através de uma coleção de rede) ou matriz call () sobre ele para obter um byte []
Michael Borgwardt
2
Outra coisa que pode ser útil é usar o enum do Guava's Charsets.UTF_8 em vez de uma String que pode gerar uma UnsupportedEncodingException. String -> Bytes: myString.getBytes(Charsets.UTF_8), e bytes -> corda: new String(myByteArray, Charsets.UTF_8).
laughing_man
24
Melhor ainda, use StandardCharsets.UTF_8. Disponível em Java 1.7+.
Kat
81

No Java7 você pode usar:

import static java.nio.charset.StandardCharsets.*;

byte[] ptext = myString.getBytes(ISO_8859_1); 
String value = new String(ptext, UTF_8); 

Isso tem a vantagem de getBytes(String)não declarar throws UnsupportedEncodingException.

Se você estiver usando uma versão Java mais antiga, poderá declarar as constantes charset:

import java.nio.charset.Charset;

public class StandardCharsets {
    public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
    public static final Charset UTF_8 = Charset.forName("UTF-8");
    //....
}
rzymek
fonte
2
Esta é a resposta certa. Se alguém quiser usar um tipo de dados string, ele poderá usá-lo no formato correto. O restante das respostas está apontando para o tipo de byte formatado.
Neeraj Shukla
Funciona em 6. Obrigado.
Itsik Mauyhas
Resposta correta para mim também. Uma coisa, porém, quando usei como acima, o caractere alemão mudou para?. Então, eu usei isso: byte [] ptext = myString.getBytes (UTF_8); Valor da string = new String (ptext, UTF_8); Isso funcionou bem.
Farhan Hafeez
3
O exemplo de código não faz sentido. Se você primeiro converter para ISO-8859-1, essa matriz de bytes não é UTF-8, portanto a próxima linha estará totalmente incorreta. Ele vai trabalhar para strings ASCII, é claro, mas então você poderia muito bem fazer uma cópia simples: String value = new String(myString);.
Alexis Wilke
76

Use em byte[] ptext = String.getBytes("UTF-8");vez de getBytes(). getBytes()usa a chamada "codificação padrão", que pode não ser UTF-8.

Peter Štibraný
fonte
9
@ Michael: ele está claramente tendo problemas para obter bytes da string. Como getBytes (codificação) está faltando? Acho que a segunda linha existe apenas para verificar se ele pode convertê-lo de volta.
Peter Štibraný
1
Eu interpreto como tendo uma String quebrada e tentando "corrigi-la" convertendo para bytes e vice-versa (mal-entendido comum). Não há indicação real de que a segunda linha esteja apenas verificando o resultado.
22611 Michael Borgwardt
@ Michael, não, não há, é apenas a minha interpretação. O seu é simplesmente diferente.
Peter Štibraný
1
@ Peter: você está certo, precisamos de esclarecimentos de Alex sobre o que ele realmente quer dizer. Não pode rescindir o downvote embora a menos que a resposta é editado ...
Michael Borgwardt
33

Uma Java String sempre é codificada internamente em UTF-16 - mas você realmente deve pensar assim: uma codificação é uma maneira de traduzir entre Strings e bytes.

Portanto, se você tiver um problema de codificação, quando tiver o String, será tarde demais para corrigir. Você precisa corrigir o local em que você cria essa String a partir de um arquivo, banco de dados ou conexão de rede.

Michael Borgwardt
fonte
1
É um erro comum acreditar que as strings são codificadas internamente como UTF-16. Geralmente são, mas se for apenas um detalhe específico da implementação da classe String. Como o armazenamento interno dos dados de caracteres não é acessível por meio da API pública, uma implementação específica de String pode decidir usar qualquer outra codificação.
precisa saber é o seguinte
3
@jarnbjo: a API declara explicitamente "Uma string representa uma string no formato UTF-16". Usar qualquer outra coisa como formato interno seria altamente ineficiente, e todas as implementações reais que eu conheço usam UTF-16 internamente. Portanto, a menos que você possa citar um que não o faça, você estará envolvido em uma divisão absurda.
Michael Borgwardt
É absurdo distinguir entre acesso público e representação interna de estruturas de dados?
jarnbjo
5
A JVM (na medida em que seja relevante para a VM) usa UTF-8 para codificação de string, por exemplo, nos arquivos de classe. A implementação do java.lang.String é dissociada da JVM e eu poderia facilmente implementar a classe para você usando qualquer outra codificação para a representação interna, se isso for realmente necessário para você perceber que sua resposta está incorreta. Usar UTF-16 como formato interno é, na maioria dos casos, altamente ineficiente também no que diz respeito ao consumo de memória e não vejo por que, por exemplo, implementações Java para hardware incorporado não otimizariam a memória em vez do desempenho.
precisa saber é o seguinte
1
@jarnbjo: E mais uma vez: enquanto você não pode dar um exemplo concreto de um JVM cuja implementação API padrão não usar internamente algo diferente de UTF-16 para implementar Cordas, minha afirmação está correta. E não, a classe String não é realmente dissociada da JVM, devido a coisas como intern () e ao pool constante.
22611 Michael Borgwardt
22

Você pode tentar assim.

byte ptext[] = myString.getBytes("ISO-8859-1"); 
String value = new String(ptext, "UTF-8"); 
user716840
fonte
1
Eu estava ficando louco. Obrigado por obter os bytes em "ISO-8859-1" primeiro foi a solução.
Gian Gomen
2
Isto está errado. Se a sua sequência incluir caracteres Unicode, a conversão para 8859-1 gerará uma exceção ou, pior, uma sequência inválida (talvez a sequência sem esses caracteres com o ponto de código 0x100 ou mais).
Alexis Wilke
12

Em um momento, passei por esse problema e consegui resolvê-lo da seguinte maneira

primeiro eu preciso importar

import java.nio.charset.Charset;

Então eu tive que declarar uma constante para usar UTF-8eISO-8859-1

private static final Charset UTF_8 = Charset.forName("UTF-8");
private static final Charset ISO = Charset.forName("ISO-8859-1");

Então eu poderia usá-lo da seguinte maneira:

String textwithaccent="Thís ís a text with accent";
String textwithletter="Ñandú";

text1 = new String(textwithaccent.getBytes(ISO), UTF_8);
text2 = new String(textwithletter.getBytes(ISO),UTF_8);
Quimbo
fonte
1
solução perfeita.
Tunde Pizzle
9
String value = new String(myString.getBytes("UTF-8"));

e, se você quiser ler um arquivo de texto com o código "ISO-8859-1":

String line;
String f = "C:\\MyPath\\MyFile.txt";
try {
    BufferedReader br = Files.newBufferedReader(Paths.get(f), Charset.forName("ISO-8859-1"));
    while ((line = br.readLine()) != null) {
        System.out.println(new String(line.getBytes("UTF-8")));
    }
} catch (IOException ex) {
    //...
}
fedesanp
fonte
2

Eu usei o código abaixo para codificar o caractere especial, especificando o formato de codificação.

String text = "This is an example é";
byte[] byteText = text.getBytes(Charset.forName("UTF-8"));
//To get original string from byte.
String originalString= new String(byteText , "UTF-8");
laxman954
fonte
2

Um rápido guia passo a passo sobre como configurar a codificação padrão do NetBeans UTF-8. Como resultado, o NetBeans criará todos os novos arquivos na codificação UTF-8.

Guia passo a passo de codificação padrão do NetBeans UTF-8

  • Vá para a pasta etc no diretório de instalação do NetBeans

  • Edite o arquivo netbeans.conf

  • Encontre a linha netbeans_default_options

  • Adicione -J-Dfile.encoding = UTF-8 entre aspas dentro dessa linha

    (exemplo netbeans_default_options="-J-Dfile.encoding=UTF-8":)

  • Reinicie o NetBeans

Você define a codificação padrão do NetBeans UTF-8.

Suas netbeans_default_options podem conter parâmetros adicionais dentro das aspas. Nesse caso, adicione -J-Dfile.encoding = UTF-8 no final da sequência. Separe-o com espaço de outros parâmetros.

Exemplo:

netbeans_default_options = "- J-client -J-Xss128m -J-Xms256m -J-XX: PermSize = 32m -J-Dapple.laf.useScreenMenuBar = true -JDapple.awt.graphics.UseQuartz = true -J-Dsun. java2d.noddraw = verdadeiro -J-Dsun.java2d.dpiaware = verdadeiro -J-Dsun.zip.disableMemoryMapping = verdadeiro -J-Dfile.encoding = UTF-8 "

aqui está o link para mais detalhes

Mr. Laeeq Khan
fonte
0

Isso resolveu meu problema

    String inputText = "some text with escaped chars"
    InputStream is = new ByteArrayInputStream(inputText.getBytes("UTF-8"));
Prasanth RJ
fonte