Ich habe eine Zeichenfolge mit maskierten Unicode- Zeichen \uXXXX
und möchte sie in reguläre Unicode-Buchstaben konvertieren. Zum Beispiel:
"\u0048\u0065\u006C\u006C\u006F World"
soll werden
"Hello World"
Ich weiß, dass beim Drucken der ersten Zeichenfolge diese bereits angezeigt wird Hello world
. Mein Problem ist, dass ich Dateinamen aus einer Datei lese und dann nach ihnen suche. Die Dateinamen in der Datei werden mit Unicode-Codierung maskiert. Wenn ich nach den Dateien suche, kann ich sie nicht finden, da nach einer Datei mit \uXXXX
ihrem Namen gesucht wird .
\u0048
istH
- sie sind ein und dasselbe. Zeichenfolgen in Java sind in Unicode.a
,b
,$
,£
usw.) zu den ganzen Zahlen. Das Symbol hatA
beispielsweise die Nummer 65 und\n
ist 10. Dies hat nichts damit zu tun, wie Zeichenfolgen oder Zeichen auf der Festplatte oder in einer Textdatei dargestellt werden. UTF-8 ist eine Spezifikation (dh Codierung), wie diese Ganzzahlen (dh Symbole) als Bytes (Bitfolgen) dargestellt werden, damit sie eindeutig aus einer Datei geschrieben und gelesen werden können.Antworten:
Technisch gesehen:
String myString = "\u0048\u0065\u006C\u006C\u006F World";
konvertiert es automatisch in
"Hello World"
, also gehe ich davon aus, dass Sie die Zeichenfolge aus einer Datei einlesen. Um es in "Hallo" umzuwandeln, müssen Sie den Text in die separaten Unicode-Ziffern analysieren (nehmen Sie die\uXXXX
und erhalten Sie einfachXXXX
)Integer.ParseInt(XXXX, 16)
, um einen Hex-Wert zu erhalten, und dann den Fall,char
um das tatsächliche Zeichen zu erhalten.Bearbeiten: Code, um dies zu erreichen:
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
quelle
Das Apache Commons Lang StringEscapeUtils.unescapeJava () kann es ordnungsgemäß dekodieren.
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
quelle
Sie können
StringEscapeUtils
von Apache Commons Lang verwenden , dh:String Title = StringEscapeUtils.unescapeJava("\\u0048\\u0065\\u006C\\u006C\\u006F");
quelle
Diese einfache Methode funktioniert in den meisten Fällen, stolpert jedoch über "u005Cu005C", das in die Zeichenfolge "\ u0048" dekodiert werden soll, aber tatsächlich "H" dekodiert, wenn der erste Durchgang "\ u0048" als Arbeitszeichenfolge erzeugt wird dann von der while-Schleife erneut verarbeitet.
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; }
quelle
Kürzere Version:
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; }
quelle
StringEscapeUtils aus der Bibliothek org.apache.commons.lang3 ist ab 3.6 veraltet .
Sie können also stattdessen die neue Commons-Text- Bibliothek verwenden:
compile 'org.apache.commons:commons-text:1.9' OR <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-text</artifactId> <version>1.9</version> </dependency>
Beispielcode:
quelle
Aus Ihrer Frage geht nicht ganz klar hervor, aber ich gehe davon aus, dass Sie sagen, dass Sie eine Datei haben, in der jede Zeile dieser Datei ein Dateiname ist. Und jeder Dateiname ist ungefähr so:
Mit anderen Worten, sind die Zeichen in der Datei von Dateinamen
\
,u
,0
,0
,4
,8
und so weiter.Wenn ja, wird erwartet, was Sie sehen. Java übersetzt nur
\uXXXX
Sequenzen in String-Literalen im Quellcode (und beim Einlesen gespeicherterProperties
Objekte). Wenn Sie die Inhalte lesen Datei , die Sie Sie eine Zeichenfolge der Zeichen bestehend haben\
,u
,0
,0
,4
,8
und so weiter und nicht die ZeichenfolgeHello
.So müssen Sie diese Zeichenfolge analysieren die extrahieren
0048
,0065
, Stücke usw. und sie dann konvertierenchar
s und einen String aus diesen machenchar
s und dann die Zeichenfolge an die Routine übergeben , die die Datei öffnet.quelle
Aktualisierungen bezüglich der Antworten, die die Verwendung von The Apache Commons Langs vorschlagen : StringEscapeUtils.unescapeJava () - es war veraltet,
Der Ersatz ist Apache Commons Text ‚s StringEscapeUtils.unescapeJava ()
quelle
Ich wollte nur meine Version mit Regex beisteuern:
private static final String UNICODE_REGEX = "\\\\u([0-9a-f]{4})"; private static final Pattern UNICODE_PATTERN = Pattern.compile(UNICODE_REGEX); ... String message = "\u0048\u0065\u006C\u006C\u006F World"; Matcher matcher = UNICODE_PATTERN.matcher(message); StringBuffer decodedMessage = new StringBuffer(); while (matcher.find()) { matcher.appendReplacement( decodedMessage, String.valueOf((char) Integer.parseInt(matcher.group(1), 16))); } matcher.appendTail(decodedMessage); System.out.println(decodedMessage.toString());
quelle
Ich habe eine leistungsfähige und fehlerfreie Lösung geschrieben:
public static final String decode(final String in) { int p1 = in.indexOf("\\u"); if (p1 < 0) return in; StringBuilder sb = new StringBuilder(); while (true) { int p2 = p1 + 6; if (p2 > in.length()) { sb.append(in.subSequence(p1, in.length())); break; } try { int c = Integer.parseInt(in.substring(p1 + 2, p1 + 6), 16); sb.append((char) c); p1 += 6; } catch (Exception e) { sb.append(in.subSequence(p1, p1 + 2)); p1 += 2; } int p0 = in.indexOf("\\u", p1); if (p0 < 0) { sb.append(in.subSequence(p1, in.length())); break; } else { sb.append(in.subSequence(p1, p0)); p1 = p0; } } return sb.toString(); }
quelle
Versuchen
private static final Charset UTF_8 = Charset.forName("UTF-8"); private String forceUtf8Coding(String input) {return new String(input.getBytes(UTF_8), UTF_8))}
quelle
Ein einfacher Weg, den ich mit JsonObject kenne:
try { JSONObject json = new JSONObject(); json.put("string", myString); String converted = json.getString("string"); } catch (JSONException e) { e.printStackTrace(); }
quelle
Hier ist meine Lösung ...
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; } };
quelle
Schnell
fun unicodeDecode(unicode: String): String { val stringBuffer = StringBuilder() var i = 0 while (i < unicode.length) { if (i + 1 < unicode.length) if (unicode[i].toString() + unicode[i + 1].toString() == "\\u") { val symbol = unicode.substring(i + 2, i + 6) val c = Integer.parseInt(symbol, 16) stringBuffer.append(c.toChar()) i += 5 } else stringBuffer.append(unicode[i]) i++ } return stringBuffer.toString() }
quelle
Eigentlich habe ich eine Open Source-Bibliothek geschrieben, die einige Dienstprogramme enthält. Eine davon ist die Konvertierung einer Unicode-Sequenz in String und umgekehrt. Ich fand es sehr nützlich. Hier ist das Zitat aus dem Artikel über diese Bibliothek über Unicode-Konverter:
Hier ist der Link zum gesamten Artikel, der erklärt, welche Dienstprogramme die Bibliothek hat und wie die Bibliothek sie verwenden kann. Es ist als Maven-Artefakt oder als Quelle von Github erhältlich. Es ist sehr einfach zu bedienen. Open Source Java-Bibliothek mit Stack-Trace-Filterung, Silent String-Parsing-Unicode-Konverter und Versionsvergleich
quelle
Für Java 9+ können Sie die neue replaceAll- Methode der Matcher- Klasse verwenden.
private static final Pattern UNICODE_PATTERN = Pattern.compile("\\\\u([0-9A-Fa-f]{4})"); public static String unescapeUnicode(String unescaped) { return UNICODE_PATTERN.matcher(unescaped).replaceAll(r -> String.valueOf((char) Integer.parseInt(r.group(1), 16))); } public static void main(String[] args) { String originalMessage = "\\u0048\\u0065\\u006C\\u006C\\u006F World"; String unescapedMessage = unescapeUnicode(originalMessage); System.out.println(unescapedMessage); }
Ich glaube, der Hauptvorteil dieses Ansatzes gegenüber unescapeJava von StringEscapeUtils (abgesehen davon, dass keine zusätzliche Bibliothek verwendet wird) besteht darin, dass Sie nur die Unicode-Zeichen konvertieren können (wenn Sie dies wünschen), da letztere alle maskierten Java-Zeichen (wie \ n oder \ t) konvertieren ). Wenn Sie lieber alle maskierten Zeichen konvertieren möchten, ist die Bibliothek die beste Option.
quelle
@NominSim Möglicherweise gibt es ein anderes Zeichen, daher sollte ich es anhand der Länge erkennen.
private String forceUtf8Coding(String str) { str = str.replace("\\",""); String[] arr = str.split("u"); StringBuilder text = new StringBuilder(); for(int i = 1; i < arr.length; i++){ String a = arr[i]; String b = ""; if (arr[i].length() > 4){ a = arr[i].substring(0, 4); b = arr[i].substring(4); } int hexVal = Integer.parseInt(a, 16); text.append((char) hexVal).append(b); } return text.toString(); }
quelle
UnicodeUnescaper
vonorg.apache.commons:commons-text
ist auch akzeptabel.new UnicodeUnescaper().translate("\u0048\u0065\u006C\u006C\u006F World")
kehrt zurück"Hello World"
quelle
Eine alternative Möglichkeit, dies zu erreichen, könnte die Verwendung von
chars()
Java 9 sein. Dies kann verwendet werden, um die Zeichen zu durchlaufen und sicherzustellen, dass alle Zeichen, die einem Ersatzcodepunkt zugeordnet sind, nicht interpretiert durchlaufen werden. Dies kann verwendet werden als: -String myString = "\u0048\u0065\u006C\u006C\u006F World"; myString.chars().forEach(a -> System.out.print((char)a)); // would print "Hello World"
quelle
Ich stellte fest, dass sich viele der Antworten nicht mit dem Thema "Ergänzende Zeichen" befassten. Hier ist der richtige Weg, um es zu unterstützen. Keine Bibliotheken von Drittanbietern, reine Java-Implementierung.
http://www.oracle.com/us/technologies/java/supplementary-142654.html
public static String fromUnicode(String unicode) { String str = unicode.replace("\\", ""); String[] arr = str.split("u"); StringBuffer text = new StringBuffer(); for (int i = 1; i < arr.length; i++) { int hexVal = Integer.parseInt(arr[i], 16); text.append(Character.toChars(hexVal)); } return text.toString(); } public static String toUnicode(String text) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < text.length(); i++) { int codePoint = text.codePointAt(i); // Skip over the second char in a surrogate pair if (codePoint > 0xffff) { i++; } String hex = Integer.toHexString(codePoint); sb.append("\\u"); for (int j = 0; j < 4 - hex.length(); j++) { sb.append("0"); } sb.append(hex); } return sb.toString(); } @Test public void toUnicode() { System.out.println(toUnicode("😊")); System.out.println(toUnicode("🥰")); System.out.println(toUnicode("Hello World")); } // output: // \u1f60a // \u1f970 // \u0048\u0065\u006c\u006c\u006f\u0020\u0057\u006f\u0072\u006c\u0064 @Test public void fromUnicode() { System.out.println(fromUnicode("\\u1f60a")); System.out.println(fromUnicode("\\u1f970")); System.out.println(fromUnicode("\\u0048\\u0065\\u006c\\u006c\\u006f\\u0020\\u0057\\u006f\\u0072\\u006c\\u0064")); } // output: // 😊 // 🥰 // Hello World
quelle
Lösung für Kotlin:
val sourceContent = File("test.txt").readText(Charset.forName("windows-1251")) val result = String(sourceContent.toByteArray())
Kotlin verwendet UTF-8 überall als Standardcodierung.
Methode
toByteArray()
hat Standardargument -Charsets.UTF_8
.quelle
String(string.toByteArray())
erreicht buchstäblich nichts.toByteArray()
hat Standardargument mitCharsets.UTF_8
. Anschließend erstellen Sie eine Zeichenfolge aus Bytearray mit der erforderlichen Codierung. Ich habe heute mitwindows-1251
utf-8 getestet , es funktioniert. Außerdem habe ich einen Vergleich auf Byte-Ebene durchgeführt :)