Come convertire una stringa con codifica Unicode in una stringa di lettere

Ho una stringa con codifica Unicode , \uXXXX , e voglio convertirla in una lettera normale ( UTF-8 ). Per esempio:

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

dovrebbe diventare

 "Hello World" 

So che quando stampo la stringa mostra Hello world . Il mio problema è che leggo i nomi dei file da un file su una macchina Unix, e quindi li cerco. I nomi dei file sono con codifica Unicode e quando cerco i file, non riesco a trovarli, poiché cerca un file con \uXXXX nel nome.

Tecnicamente facendo:

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

lo converte automaticamente in "Hello World" , quindi presumo che tu stia leggendo nella stringa da qualche file. Per convertirlo in “Hello” dovrai analizzare il testo nelle cifre Unicode separate, (prendi il \uXXXX e ottieni XXXX ) quindi \uXXXX Integer.ParseInt(XXXX, 16) per ottenere un valore esadecimale e poi caso che char per ottenere il carattere reale.

Modifica: qualche codice per realizzare questo:

 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 

L’ Apache Commons Lang StringEscapeUtils.unescapeJava () può decodificarlo correttamente.

 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 

È ansible utilizzare StringEscapeUtils da Apache Commons Lang , ovvero:

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

Byte Codifiche e stringhe

In java per la conversione del stream di byte (byte []) nella stringa (String) e di nuovo nella class String ha le seguenti caratteristiche:

Constructor String (byte [] bytes, String enc) riceve il stream di input dei byte con la loro codifica; se la codifica viene omessa, verrà accettata di default

getBytes Method (String enc) restituisce un stream di byte registrato nella codifica specificata; la codifica può anche essere omessa.

 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(); } 

AGGIORNARE:

Poiché Java 1.7 utilizza 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); 

Questo semplice metodo funzionerà per la maggior parte dei casi, ma potrebbe saltare su qualcosa come “u005Cu005C” che dovrebbe decodificare sulla stringa “\ u0048” ma in realtà decodificherà “H” mentre il primo passaggio produce “\ u0048” come stringa di lavoro che quindi viene nuovamente elaborato dal ciclo 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; } 

Non è completamente chiaro dalla tua domanda, ma presumo che tu abbia un file in cui ogni riga di quel file è un nome di file. E ogni nome file è qualcosa del genere:

 \u0048\u0065\u006C\u006C\u006F 

In altre parole, i caratteri nel file dei nomi di file sono \ , u , 0 , 0 , 4 , 8 e così via.

Se è così, quello che stai vedendo è previsto. Java \uXXXX sequenze \uXXXX in stringhe letterali nel codice sorgente (e durante la lettura in oggetti Properties memorizzati). Quando leggi il contenuto del file avrai una stringa composta dai caratteri \ , u , 0 , 0 , 4 , 8 e così via e non dalla stringa Hello .

Quindi dovrai analizzare quella stringa per estrarre i pezzi 0048 , 0065 , ecc. E poi convertirli in char e creare una stringa da quei char e quindi passare quella stringa alla routine che apre il file.

provare

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

Versione più breve:

 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; } 

un modo semplice che conosco usando JsonObject:

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

In realtà, ho scritto una libreria Open Source che contiene alcune utilità. Uno di questi è la conversione di una sequenza Unicode in String e viceversa. L’ho trovato molto utile. Ecco la citazione dall’articolo su questa libreria sul convertitore Unicode:

Class StringUnicodeEncoderDecoder ha metodi che possono convertire una stringa (in qualsiasi lingua) in una sequenza di caratteri Unicode e viceversa. Ad esempio, una stringa “Hello World” verrà convertita in

“\ u0048 \ u0065 \ u006c \ u006c \ u006f \ u0057 \ u006f \ u006 \ u006c \ u0064”

e può essere ripristinato.

Ecco il link all’intero articolo che spiega quali utilità ha la libreria e come farla utilizzare dalla libreria. È disponibile come artefatto Maven o come fonte da Github. È molto facile da usare Libreria Java Open Source con filtro di tracciabilità dello stack, conversione Unicode del convertitore di stringhe Silent e confronto delle versioni

Ecco la mia soluzione …

  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; } }; 

Soluzione per Kotlin:

 val result = String(someText.toByteArray()) 

Kotlin usa UTF-8 ovunque come codifica predefinita

Inoltre puoi implementarlo come estensione per la class String:

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

e quindi usarlo semplice:

 val result = someText.unescape() 

😉

Un modo alternativo per ottenere ciò potrebbe essere quello di utilizzare chars() introdotto con Java 9, che può essere utilizzato per iterare sui personaggi assicurandosi che ogni char che mappa ad un punto di codice surrogato sia passato attraverso uninterpreted. Questo può essere usato come: –

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