2010-11-23 9 views
1

Wie kann ich so genannte "php Unicode" (link to php unicode) zu normalen Zeichen über Java konvertieren? Beispiel \ xEF \ xBC \ xA1 -> A. Gibt es eingebettete Methoden in jdk oder sollte ich Regex für diese Konvertierung verwenden?Convert "php Unicode" in Zeichen

+1

Ist Ihre Eingabe im Zeichenfolgenformat ('\ xNN') oder im Binärformat? – casablanca

+0

Ja, String \ xNN –

Antwort

1

Das betreffende Zeichen ist U + FF21 (FULLWIDTH LATIN CAPITAL LETTER A). Das PHP-Formular (\ xEF \ xBC \ xA1) ist eine UTF-8-codierte Oktettsequenz.

Um diese Sequenz zu einem Java-String zu dekodieren (die immer UTF-16 ist), würden Sie den folgenden Code verwenden:

// \xEF\xBC\xA1 
byte[] utf8 = { (byte) 0xEF, (byte) 0xBC, (byte) 0xA1 }; 
String utf16 = new String(utf8, Charset.forName("UTF-8")); 

// print the char as hex 
for(char ch : utf16.toCharArray()) { 
    System.out.format("%02x%n", (int) ch); 
} 

Wenn Sie die Daten aus einem Stringliteral könnte entschlüsseln wollen Verwenden Sie den Code dieses Formulars:

public static void main(String[] args) { 
    String utf16 = transformString("This is \\xEF\\xBC\\xA1 string"); 
    for (char ch : utf16.toCharArray()) { 
    System.out.format("%s %02x%n", ch, (int) ch); 
    } 
} 

private static final Pattern SEQ 
          = Pattern.compile("(\\\\x\\p{Alnum}\\p{Alnum})+"); 

private static String transformString(String encoded) { 
    StringBuilder decoded = new StringBuilder(); 
    Matcher matcher = SEQ.matcher(encoded); 
    int last = 0; 
    while (matcher.find()) { 
    decoded.append(encoded.substring(last, matcher.start())); 
    byte[] utf8 = toByteArray(encoded.substring(matcher.start(), matcher.end())); 
    decoded.append(new String(utf8, Charset.forName("UTF-8"))); 
    last = matcher.end(); 
    } 
    return decoded.append(encoded.substring(last, encoded.length())).toString(); 
} 

private static byte[] toByteArray(String hexSequence) { 
    byte[] utf8 = new byte[hexSequence.length()/4]; 
    for (int i = 0; i < utf8.length; i++) { 
    int offset = i * 4; 
    String hex = hexSequence.substring(offset + 2, offset + 4); 
    utf8[i] = (byte) Integer.parseInt(hex, 16); 
    } 
    return utf8; 
} 
2

Zuerst müssen Sie die Bytes aus der Zeichenfolge in ein Bytearray holen, ohne sie zu ändern, und dann das Bytearray als UTF-8-Zeichenfolge dekodieren. Der einfachste Weg, die Zeichenkette in ein Byte-Array zu bringen, besteht darin, sie mit ISO-8859-1 zu codieren, die jedes Zeichen mit einem Unicode-Wert von weniger als 256 auf ein Byte mit dem gleichen Wert (oder dem entsprechenden negativen Wert)

abbildet
String phpUnicode = "\u00EF\u00BC\u00A1" 
byte[] bytes = phpUnicode.getBytes("ISO-8859-1"); // maps to bytes with the same ordinal value 
String javaString = new String(bytes, "UTF-8"); 
System.out.println(javaString); 

bearbeiten
die obige wandelt die UTF-8 in das Unicode-Zeichen. Wenn Sie dann auf einen vernünftigen ASCII-äquivalent konvertieren mögen, gibt es kein Standardverfahren, das zu tun, aber see this question

bearbeiten
ich davon ausgegangen, dass Sie eine Zeichenfolge, die Zeichen hatten, die den gleichen Ordnungswert als UTF hatte -8-Sequenz, aber sie zeigen, dass die Zeichenfolge buchstäblich die Escape-Sequenz enthält, wie in:

String phpUnicode = "\\xEF\\xBC\\xA1"; 

Das JDK hat keine integrierten Methoden Strings so konvertieren, so müssen Sie Ihre eigenen verwenden Regex. Da wir schließlich eine utf-8-Byte-Sequenz in einen String konvertieren wollen, müssen wir einen Byte-Array einzurichten, vielleicht mit:

Pattern oneChar = Pattern.compile("\\\\x([0-9A-F]{2})|(.)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); 
Matcher matcher = oneChar.matcher(phpUnicode); 
ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 

while (matcher.find()) { 
    int ch; 
    if (matcher.group(1) == null) { 
     ch = matcher.group(2).charAt(0); 
    } 
    else { 
     ch = Integer.parseInt(matcher.group(1), 16); 
    } 
    bytes.write((int) ch); 
} 
String javaString = new String(bytes.toByteArray(), "UTF-8"); 
System.out.println(javaString); 

Dies wird einen UTF-8-Strom durch die Umwandlung \ xab Sequenzen erzeugen . Dieser UTF-8-Stream wird dann in eine Java-Zeichenfolge konvertiert. Es ist wichtig zu beachten, dass jedes Zeichen, das nicht Teil einer Escape-Sequenz ist, in ein Byte konvertiert wird, das den 8 Bit-Bits des Unicode-Zeichens entspricht. Dies funktioniert gut für ASCII, kann aber Transkodierungsprobleme für nicht-ASCII-Zeichen verursachen.

@McDowell:
die Sequenz:

String phpUnicode = "\u00EF\u00BC\u00A1" 
byte[] bytes = phpUnicode.getBytes("ISO-8859-1"); 

erzeugt ein Byte-Array, wie viele Bytes enthalten, wie die ursprüngliche Zeichenfolge Zeichen enthält, und für jedes Zeichen mit einer Unicode-Wert unter 256, den gleichen numerischen Wert gespeichert wird im Byte-Array.

Das Zeichen FULLWIDTH LATIN CAPITAL LETTER A (U + FF41) ist im ursprünglichen String nicht vorhanden, daher ist die Tatsache, dass es nicht in ISO-8859-1 enthalten ist, irrelevant.

Ich weiß, dass Umcodierung Fehler auftreten können, wenn Sie Zeichen Bytes umwandeln, das ist, warum ich sagte, dass die ISO-8859-1 würde nur „jedes Zeichen mit einem Unicode-Wert Karte weniger als 256 zu einem Byte mit dem gleichen Wert“

+0

Schön, aber als ich \ xNN \ xNN Zeichenfolge in Unicode-Zeichenfolge konvertieren muss, habe ich eine Regexp geschrieben, die NN-Zeichen fängt, aber wie kann ich eine Unicode-Zeichenfolge von NN erstellen? F. e. Ich habe NN Ich brauche "\ u0NN" (String-Zusatz funktioniert hier nicht) –

+0

Java-Zeichenfolgen sind UTF-16; versuchen, UTF-8 in ihnen darzustellen ('" \ u00eF \ u00BC \ u00A1 "') wird nur zu Transcoding Bugs führen. In jedem Fall ist das Zeichen FULLWIDTH LATIN CAPITAL LETTER A in ISO-8859-1 nicht vorhanden. – McDowell

+0

@McDowell: Siehe meine 2. Bearbeitung –