Como converter uma string com codificação Unicode em uma string de letras

Eu tenho uma string com codificação Unicode , \uXXXX , e eu quero convertê-lo em uma letra normal ( UTF-8 ). Por exemplo:

 String myString = "\u0048\u0065\u006C\u006C\u006F World"; 

Deve se tornar

 "Hello World" 

Eu sei que quando eu imprimo a corda mostra Hello world . Meu problema é que eu leio nomes de arquivos de um arquivo em uma máquina Unix, e depois procuro por eles. Os nomes de arquivos estão com a codificação Unicode e, quando procuro os arquivos, não consigo localizá-los, pois ele procura um arquivo com \uXXXX em seu nome.

Tecnicamente fazendo:

 String myString = "\u0048\u0065\u006C\u006C\u006F World"; 

O converte automaticamente para "Hello World" , então presumo que você esteja lendo na string de algum arquivo. Para convertê-lo para “Hello” você terá que analisar o texto nos dígitos unicode separados, (pegue o \uXXXX e é só pegar XXXX ) então faça Integer.ParseInt(XXXX, 16) para obter um valor hexadecimal e então caso que char para obter o personagem real.

Edit: Algum código para conseguir isso:

 String str = myString.split(" ")[0]; str = str.replace("\\",""); String[] arr = str.split("u"); String text = ""; for(int i = 1; i < arr.length; i++){ int hexVal = Integer.parseInt(arr[i], 16); text += (char)hexVal; } // Text will now have Hello 

O Apache Commons Lang StringEscapeUtils.unescapeJava () pode decodificá-lo corretamente.

 import org.apache.commons.lang.StringEscapeUtils; @Test public void testUnescapeJava() { String sJava="\\u0048\\u0065\\u006C\\u006C\\u006F"; System.out.println("StringEscapeUtils.unescapeJava(sJava):\n" + StringEscapeUtils.unescapeJava(sJava)); } output: StringEscapeUtils.unescapeJava(sJava): Hello 

Você pode usar o StringEscapeUtils do Apache Commons Lang , ou seja:

 String Title = StringEscapeUtils.unescapeJava("\u0048\u0065\u006C\u006C\u006F"); 

Codificações e cordas de bytes

Em java para conversão do stream de bytes (byte []) na string (String) e de volta para a class String tem os seguintes resources:

Construtor String (byte [] bytes, String enc) recebe o stream de input de bytes com sua codificação; se a codificação for omitida, ela será aceita por padrão

getBytes Method (String enc) retorna um stream de bytes gravado na codificação especificada; codificação também pode ser omitida.

 try { String myString = "\u0048\u0065\u006C\u006C\u006F World"; byte[] utf8Bytes = myString.getBytes("UTF8"); String text = new String(utf8Bytes,"UTF8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } 

ATUALIZAR:

Desde o Java 1.7 use StandardCharsets.UTF_8 :

 String utf8Text = "\u0048\u0065\u006C\u006C\u006F World"; byte[] bytes = utf8Text.getBytes(StandardCharsets.UTF_8); String text = new String(bytes, StandardCharsets.UTF_8); 

Este método simples funcionará para a maioria dos casos, mas tropeçaria em algo como “u005Cu005C”, que deveria decodificar a string “\ u0048”, mas decodificaria “H”, já que a primeira passagem produz “\ u0048” como a string de trabalho que então é processado novamente pelo loop while.

 static final String decode(final String in) { String working = in; int index; index = working.indexOf("\\u"); while(index > -1) { int length = working.length(); if(index > (length-6))break; int numStart = index + 2; int numFinish = numStart + 4; String substring = working.substring(numStart, numFinish); int number = Integer.parseInt(substring,16); String stringStart = working.substring(0, index); String stringEnd = working.substring(numFinish); working = stringStart + ((char)number) + stringEnd; index = working.indexOf("\\u"); } return working; } 

Não está totalmente claro na sua pergunta, mas estou supondo que você tenha um arquivo em que cada linha desse arquivo é um nome de arquivo. E cada nome de arquivo é algo assim:

 \u0048\u0065\u006C\u006C\u006F 

Em outras palavras, os caracteres no arquivo de nomes de arquivos são \ , u , 0 , 0 , 4 , 8 e assim por diante.

Se sim, o que você está vendo é esperado. Java traduz apenas seqüências \uXXXX em literais de seqüência de caracteres no código-fonte (e ao ler em objects de Properties armazenadas). Quando você ler o conteúdo do arquivo, você terá uma string contendo os caracteres \ , u , 0 , 0 , 4 , 8 e assim por diante, e não a string Hello .

Portanto, você precisará analisar essa cadeia para extrair as partes 0048 , 0065 etc. e, em seguida, convertê-las em char s e criar uma cadeia desses char e, em seguida, passar essa cadeia para a rotina que abre o arquivo.

experimentar

 private static final Charset UTF_8 = Charset.forName("UTF-8"); private String forceUtf8Coding(String input) {return new String(input.getBytes(UTF_8), UTF_8))} 

Versão mais curta:

 public static String unescapeJava(String escaped) { if(escaped.indexOf("\\u")==-1) return escaped; String processed=""; int position=escaped.indexOf("\\u"); while(position!=-1) { if(position!=0) processed+=escaped.substring(0,position); String token=escaped.substring(position+2,position+6); escaped=escaped.substring(position+6); processed+=(char)Integer.parseInt(token,16); position=escaped.indexOf("\\u"); } processed+=escaped; return processed; } 

Uma maneira fácil que eu conheço usando o JsonObject:

 try { JSONObject json = new JSONObject(); json.put("string", myString); String converted = json.getString("string"); } catch (JSONException e) { e.printStackTrace(); } 

Na verdade, eu escrevi uma biblioteca Open Source que contém alguns utilitários. Uma delas é converter uma sequência Unicode em String e vice-versa. Eu achei muito útil. Aqui está a citação do artigo sobre esta biblioteca sobre o conversor Unicode:

Classe StringUnicodeEncoderDecoder possui methods que podem converter uma String (em qualquer idioma) em uma seqüência de caracteres Unicode e vice-versa. Por exemplo, uma String “Hello World” será convertida em

“\ u0048 \ u0065 \ u006c \ u006c \ u006f \ u0020 \ u0057 \ u006f \ u0072 \ u006c \ u0064”

e pode ser restaurado de volta.

Aqui está o link para o artigo inteiro que explica o que os utilitários da biblioteca têm e como obter a biblioteca para usá-lo. Está disponível como artefato Maven ou como fonte do Github. É muito fácil de usar. Biblioteca Java de código-fonte aberto com filtragem de rastreio de pilha, Conversor Unicode de análise de sequência silenciosa e Comparação de versão

Aqui está a minha solução …

  String decodedName = JwtJson.substring(startOfName, endOfName); StringBuilder builtName = new StringBuilder(); int i = 0; while ( i < decodedName.length() ) { if ( decodedName.substring(i).startsWith("\\u")) { i=i+2; builtName.append(Character.toChars(Integer.parseInt(decodedName.substring(i,i+4), 16))); i=i+4; } else { builtName.append(decodedName.charAt(i)); i = i+1; } }; 

Solução para Kotlin:

 val result = String(someText.toByteArray()) 

Kotlin usa UTF-8 em todos os lugares como codificação padrão

Além disso, você pode implementá-lo como extensão para a class String:

 fun String.unescape(): String { return String(this.toByteArray()) } 

e depois use-o de maneira simples:

 val result = someText.unescape() 

😉

Uma maneira alternativa de realizar isso poderia ser fazer uso de chars() introduzidos com o Java 9, isso pode ser usado para iterar os caracteres, certificando-se de que qualquer caractere mapeado para um ponto de código substituto seja passado através de não interpretado. Isso pode ser usado como: –

 String myString = "\u0048\u0065\u006C\u006C\u006F World"; myString.chars().forEach(a -> System.out.print((char)a)); // would print "Hello World"