Nach einer kleinen Überprüfung des Zeichencodes wurde mir klar, dass ich mir nie Sorgen um Unicode-Ersatzpaare gemacht hatte. Also habe ich geübt, Ersatzpaar-Zeichenketten zusammenzusetzen und die Anzahl der Zeichen in Java zu zählen, die ich auch bei der Arbeit verarbeite.
Bis Java 1.4 wurden Ersatzpaare nicht berücksichtigt, aber in 1.5 wurde eine API hinzugefügt, die Ersatzpaare berücksichtigt. Daher versuchen wir im obigen Testcode, die API bis zur 1.4-Serie und die in 1.5 hinzugefügte API aufzurufen und das Verhalten zu vergleichen.
Lassen Sie uns zunächst ein Ersatzpaar mit dem Typ char ausdrücken. Der obere Ersatz und der untere Ersatz werden als separate Zeichenvariablen getrennt und in das Array aufgenommen.
char c1 = '\u3042'; // HIRAGANA LETTER A, cp=12354
char c2 = '\uD842'; // tuchi-yoshi (high), cp=134071
char c3 = '\uDFB7'; // tuchi-yoshi (low), cp=134071
char c4 = '\u30D5'; // katakana fu, cp=12501
char c5 = '\u309A'; // handakuten, cp=12442
char c6 = '\uD842'; // kuchi + shichi (high), cp=134047
char c7 = '\uDF9F'; // kuchi + shichi (low), cp=134047
String s = new String(new char[] { c1, c2, c3, c4, c5, c6, c7 });
assertEquals(s, "\u3042\uD842\uDFB7\u30D5\u309A\uD842\uDF9F");
Versuchen Sie dann, die Zeichenfolge mit "String.length ()" oder "String.charAt ()" zu kopieren, wobei keine Ersatzpaare berücksichtigt werden. Wenn man sich das endgültige "assertEquals ()" ansieht, stimmt es mit der aus "int []" generierten Zeichenfolge mit der Aufteilung des Ersatzpaars überein. Sie können sehen, wie der obere und der untere Ersatz als unabhängige Zeichen behandelt und kopiert werden.
int len = s.length();
assertEquals(len, 7); // ignores surrogate pair :P
int[] actualCps = new int[len];
for (int i = 0; i < len; i++) {
char c = s.charAt(i);
actualCps[i] = (int) c;
}
// Ignores surrogate pairs... :(
// BUT JavaScript unicode escape in browser accepts this format...:(
assertEquals(actualCps, new int[] { 0x3042, 0xD842, 0xDFB7, 0x30D5, 0x309A, 0xD842, 0xDF9F });
Versuchen Sie nun, String.codePointCount () und String.codePointAt () zu verwenden, um Ersatzpaare zu berücksichtigen. Wenn Sie sich das letzte "assertEquals ()" ansehen, werden Sie feststellen, dass das gepaarte Ersatzzeichen mit der hexadezimalen Zeichenfolge von Unicode-Codepunkten identisch ist. Sie können überprüfen, wie das Ersatzpaar behandelt wird, indem Sie es als ein Zeichen zählen.
int countOfCp = s.codePointCount(0, len);
assertEquals(countOfCp, 5); // GOOD.
actualCps = new int[countOfCp];
for (int i = 0, j = 0, cp; i < len; i += Character.charCount(cp)) {
cp = s.codePointAt(i);
actualCps[j++] = cp;
}
// GOOD.
assertEquals(actualCps, new int[] { 0x3042, 0x20BB7, 0x30D5, 0x309A, 0x20B9F });
Referenz:
Recommended Posts