2010-11-23 6 views

Répondre

1

Le caractère en question est U + FF21 (LETTRE MAJUSCULE LATIN A). La forme PHP (\ xEF \ xBC \ xA1) est une séquence d'octets codée en UTF-8.

Afin de décoder cette séquence à une chaîne Java (qui est toujours UTF-16), vous devez utiliser le code suivant:

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

Si vous voulez décoder les données à partir d'une chaîne littérale vous pourriez utiliser le code de ce formulaire:

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

Vous devez d'abord extraire les octets de la chaîne dans un tableau d'octets sans les modifier, puis décoder le byte-array en tant que chaîne UTF-8. La manière la plus simple d'obtenir la chaîne dans un tableau d'octets est de l'encoder en utilisant ISO-8859-1 qui mappent chaque caractère avec une valeur unicode inférieure à 256 à un octet avec la même valeur (ou l'équivalent négatif)

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

Modifier
convertis au-dessus du au caractère Unicode UTF-8. Si vous souhaitez ensuite le convertir en un équivalent ASCII raisonnable, il n'y a aucun moyen standard de le faire: mais see this question

Modifier
Je suppose que vous avez eu une chaîne contenant des caractères qui ont la même valeur ordinale que l'UTF -8 séquence, mais vous indiquez que votre chaîne contient littéralement la séquence d'échappement, comme dans:

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

JDK Nous ne connaissons aucune des méthodes intégrées pour convertir des chaînes comme celui-ci de sorte que vous aurez besoin d'utiliser votre propre regex. Puisque nous voulons finalement convertir une séquence octets utf-8 dans une chaîne, nous avons besoin de mettre en place un octet tableau, en utilisant peut-être:

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

Cela va générer un flux UTF-8 en convertissant des séquences \ xab . Ce flux UTF-8 est ensuite converti en une chaîne Java. Il est important de noter que tout caractère qui ne fait pas partie d'une séquence d'échappement sera converti en un octet équivalent aux 8 bits de poids faible du caractère unicode. Cela fonctionne bien pour ascii mais peut causer des problèmes de transcodage pour les caractères non-ascii.

@McDowell:
La séquence:

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

crée un tableau d'octets contenant autant d'octets que la chaîne d'origine comporte des caractères et pour chaque caractère avec une valeur de unicode ci-dessous 256, la même valeur numérique est stockée dans le byte-array.

Le caractère FULLWIDTH LATIN CAPITAL LETTRE A (U + FF41) n'est pas présent dans la chaîne d'origine, donc le fait qu'il ne soit pas dans ISO-8859-1 n'est pas pertinent.

Je sais que les bugs de transcodage peuvent se produire lorsque vous convertir les caractères en octets qui est la raison pour laquelle je l'ai dit que ISO-8859-1 ne ferait que « la carte tous les caractères d'une valeur unicode inférieure à 256 à un octet avec la même valeur »

+0

Bien que j'ai besoin de convertir la chaîne \ xNN \ xNN en chaîne unicode, j'ai écrit une expression rationnelle qui capture les caractères NN mais comment puis-je créer une chaîne unicode à partir de NN? F.e. j'ai NN j'ai besoin de "\ u0NN" (l'addition de chaîne ne fonctionne pas ici) –

+0

Les chaînes de Java sont UTF-16; essayer de représenter l'UTF-8 dans ceux-ci ('" \ u00EF \ u00BC \ u00A1 "') ne fera que conduire à des bogues de transcodage. Dans tous les cas, le caractère FULLWIDTH LATIN CAPITAL LETTER A n'est pas présent dans l'ISO-8859-1. – McDowell

+0

@McDowell: Voir ma 2ème édition –

Questions connexes