2010-11-23 15 views
1

Javaを介していわゆる "PHP unicode"(link to php unicode)を通常の文字に変換するにはどうすればよいですか?例\ xEF \ xBC \ xA1 - > A. jdkに埋め込みメソッドがありますか?またはこの変換に正規表現を使用する必要がありますか?"php unicode"を文字に変換する

+1

入力は文字列形式( '\ xNN')またはバイナリ形式ですか? – casablanca

+0

はい、文字列\ xNN –

答えて

1

問題のキャラクターはU + FF21(全角大文字アルファベットA)です。 PHPフォーム(\ xEF \ xBC \ xA1)は、UTF-8でエンコードされたオクテットシーケンスです。あなたは、あなたは可能性リテラル文字列からのデータをデコードする場合

// \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); 
} 

:(常にUTF-16である)JavaのString、あなたは以下のコードを使用するには、このシーケンスをデコードするために

この形式のコードを使用してください:

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

まず文字列のバイトを変更せずにバイト配列に取り出し、バイト配列をUTF-8文字列としてデコードする必要があります。

文字列をバイト配列に入れる最も簡単な方法は、Unicode値が256より小さいすべての文字を同じ値(またはそれに相当する負数)のバイトにマップするISO-8859-1を使用してコード化することです。

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

編集
は、上記のUnicode文字をUTF-8に変換します。あなたは合理的なASCII文字に変換したい場合は、それを行うの標準的な方法はありません。しかしsee this question

編集
私はあなたがUTFと同じ順序値を持っていた文字を含む文字列を持っていたと仮定-8シーケンスしかし、あなたはのように、あなたの文字列は文字通りのエスケープシーケンスが含まれていることを示しています

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

はJDKので、あなたがあなた自身を使用する必要があります。このような文字列を変換するための任意の組み込みメソッドを持っていません正規表現。我々は最終的に文字列にUTF-8バイトのシーケンスを変換したいので、私たちは多分使用して、バイト配列を設定する必要があります。

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

これは\ XABシーケンスを変換してUTF-8ストリームを生成します。 。このUTF-8ストリームはJava文字列に変換されます。エスケープシーケンスの一部ではない文字は、Unicode文字の下位8ビットに相当するバイトに変換されることに注意することが重要です。これはasciiでは問題なく動作しますが、ASCII以外の文字ではトランスコードの問題が発生する可能性があります。

@McDowell:
配列:

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

は、元の文字列が文字を持っており、256以下Unicode値と各文字のために、同じ数値が格納されている限り多くのバイトを含むバイト配列を作成しバイト配列に格納されます。

文字列FULLWIDTH LATIN CAPITAL LETTER A(U + FF41)は元のStringには存在しないため、ISO-8859-1に含まれていないということは無関係です。

私はあなたが私はISO-8859-1のみ

「を同じ値でバイト未満256 Unicode値を持つすべての文字をマップする」と述べた理由ですバイトに文字を変換するときに、トランスコーディングのバグが発生する可能性があることを知っています
+0

\ xNN \ xNN文字列をUnicode文字列に変換する必要がありますが、NN文字をキャッチする正規表現を作成しましたが、どのようにしてNNからUnicode文字列を作成できますか? F.e.私はNNが必要です "\ u0NN"(文字列の追加はここでは動作しません) –

+0

Java文字列はUTF-16です。 UTF-8を表現しようとすると( '' \ u00EF \ u00BC \ u00A1 "')、トランスコードのバグにつながるだけです。いずれにせよ、文字FULLWIDTH LATIN CAPITAL LETTER AはISO-8859-1には存在しません。 – McDowell

+0

@McDowell:私の2番目の編集を見る –

関連する問題