Es scheint, dass die Methode, die NIO vollständig nutzt, für die Implementierung der Kürzung um die Anzahl der Bytes von String empfohlen wird. Die Implementierung der auf Japanisch eingeführten Straße scheint jedoch in der Android-Umgebung nicht wie erwartet zu funktionieren.
Wenn Sie bei Google suchen, werden die folgenden Seiten oben angezeigt. http://qiita.com/ota-meshi/items/16972156c935b8b7feaa http://d.hatena.ne.jp/kameid/20090314/1237025305
Der allgemeine Ablauf dieser Implementierungen ist wie folgt.
Als ich diesen Prozess getestet habe, habe ich die folgenden Ergebnisse erhalten.
Testtyp | Ausführungsumgebung | Ergebnis |
---|---|---|
Lokaler Einheitentest | Android Studio OpenJDK | "AIUE" |
Instrumentierter Test | Android Emulator | "AIUEO" |
Die obige Implementierung wird unter der Annahme durchgeführt, dass die CharBuffer-Position 4 ist, wenn die Codierung durch Überlauf unterbrochen wird. Auf dem Android-Emulator oder dem tatsächlichen Computer wurde die Position von CharBuffer jedoch auf 5 erhöht, als die Codierung durch Overflow unterbrochen wurde, sodass die Kürzung nicht wie erwartet funktionierte.
Nur für den Fall, wenn Sie die Beschreibung der Position des Charset-Encoders überprüfen, scheint es, dass dies keine so strenge Erklärung ist. Es scheint, dass erwartet werden kann, dass sich die Position auf der Schreibseite zum Zeitpunkt des Überlaufs am Ende befindet, aber die Leseseite wird sich wahrscheinlich abhängig von der Implementierung des Überlaufurteils jedes Codierers ändern. Ich dachte.
https://docs.oracle.com/javase/jp/8/docs/api/java/nio/charset/CharsetEncoder.html Die Position des Puffers erhöht sich mit der Anzahl der gelesenen Zeichen oder der Anzahl der geschriebenen Bytes.
Als ich mich an englischsprachige Länder wandte, um bei Google zu suchen, wurde die folgende Seite eingeführt. https://theholyjava.wordpress.com/2007/11/02/truncating-utf-string-to-the-given/
Die Implementierung hier ist ungefähr wie folgt. Es ist ein Prozess, der nicht von der Position auf der Leseseite abhängt, wenn das Codieren / Decodieren abgeschlossen ist.
Mit dieser Referenz werden wir eine Implementierung vorstellen, die eine frühzeitige, unnötige Beurteilung der Kürzung beinhaltet.
public static String truncate(String text, int capacity) {
if (text == null || capacity < 0) {
throw new IllegalArgumentException("invalid parameter.");
}
Charset charset = StandardCharsets.UTF_8;
CharsetEncoder encoder = charset.newEncoder()
.onMalformedInput(CodingErrorAction.IGNORE)
.onUnmappableCharacter(CodingErrorAction.IGNORE)
.reset();
// step 0.
int estimate = text.length() * (int) Math.ceil(encoder.maxBytesPerChar());
if (estimate <= capacity) {
return text;
}
// step 1.
ByteBuffer srcBuffer = ByteBuffer.allocate(capacity);
CoderResult result = encoder.encode(CharBuffer.wrap(text), srcBuffer, true);
encoder.flush(srcBuffer);
srcBuffer.flip();
if (result.isUnderflow()) {
return text;
}
// step 2.
CharBuffer dstBuffer = CharBuffer.allocate(text.length());
CharsetDecoder decoder = charset.newDecoder()
.onMalformedInput(CodingErrorAction.IGNORE)
.onUnmappableCharacter(CodingErrorAction.IGNORE)
.reset();
decoder.decode(srcBuffer, dstBuffer, true);
decoder.flush(dstBuffer);
dstBuffer.flip();
// step 3.
return dstBuffer.toString();
}
@Test
public void truncate() throws Exception {
//1Byte Zeichen
String testA = "abcde";
String testA_len0 = "";
String testA_len1 = "a";
String testA_len4 = "abcd";
String testA_len5 = "abcde";
assertThat(StringUtil.truncate(testA, 0), is(testA_len0));
assertThat(StringUtil.truncate(testA, 1), is(testA_len1));
assertThat(StringUtil.truncate(testA, 4), is(testA_len4));
assertThat(StringUtil.truncate(testA, 5), is(testA_len5));
//3Byte Zeichen
String testB = "AIUEO";
String testB_len0 = "";
String testB_len1 = "Ah";
String testB_len4 = "AIUE";
String testB_len5 = "AIUEO";
assertThat(StringUtil.truncate(testB, 0), is(testB_len0));
assertThat(StringUtil.truncate(testB, 2), is(testB_len0));
assertThat(StringUtil.truncate(testB, 3), is(testB_len1));
assertThat(StringUtil.truncate(testB, 14), is(testB_len4));
assertThat(StringUtil.truncate(testB, 15), is(testB_len5));
//4Byte Zeichen
//5 Zeichen
// https://www.softel.co.jp/blogs/tech/archives/596
String testC = "\uD840\uDC0B\uD844\uDE3D\uD844\uDF1B\uD845\uDC6E\uD846\uDCBD";
String testC_len0 = "";
String testC_len1 = "\uD840\uDC0B";
String testC_len4 = "\uD840\uDC0B\uD844\uDE3D\uD844\uDF1B\uD845\uDC6E";
String testC_len5 = "\uD840\uDC0B\uD844\uDE3D\uD844\uDF1B\uD845\uDC6E\uD846\uDCBD";
assertThat(StringUtil.truncate(testC, 3), is(testC_len0));
assertThat(StringUtil.truncate(testC, 4), is(testC_len1));
assertThat(StringUtil.truncate(testC, 19), is(testC_len4));
assertThat(StringUtil.truncate(testC, 20), is(testC_len5));
//Kombination von 1Byte- und 3Byte-Zeichen
String testD = "A A B I C U D E E.";
String testD_len1 = "A";
String testD_len2 = "A Ah";
String testD_len9 = "A A B I C U D E E.";
String testD_len10 = "A A B I C U D E E.";
assertThat(StringUtil.truncate(testD, 1), is(testD_len1));
assertThat(StringUtil.truncate(testD, 3), is(testD_len1));
assertThat(StringUtil.truncate(testD, 4), is(testD_len2));
assertThat(StringUtil.truncate(testD, 19), is(testD_len9));
assertThat(StringUtil.truncate(testD, 20), is(testD_len10));
//Piktogramm
//Japanische Flagge, BATH
// U+1F1EF U+1F1F5, U+1F6C0
// 4+4Byte + 4Byte
// http://qiita.com/_sobataro/items/47989ee4b573e0c2adfc
String testE = "\uD83C\uDDEF\uD83C\uDDF5\uD83D\uDEC0";
String testE_len0 = "";
String testE_len1 = "\uD83C\uDDEF";
String testE_len2 = "\uD83C\uDDEF\uD83C\uDDF5";
String testE_len3 = "\uD83C\uDDEF\uD83C\uDDF5\uD83D\uDEC0";
assertThat(StringUtil.truncate(testE, 3), is(testE_len0));
assertThat(StringUtil.truncate(testE, 4), is(testE_len1));
assertThat(StringUtil.truncate(testE, 7), is(testE_len1));
assertThat(StringUtil.truncate(testE, 8), is(testE_len2));
assertThat(StringUtil.truncate(testE, 11), is(testE_len2));
assertThat(StringUtil.truncate(testE, 12), is(testE_len3));
//Stringlängenprüfung
assertEquals(1 + 1 + 1 + 1 + 1, testA.length());
assertEquals(1 + 1 + 1 + 1 + 1, testB.length());
assertEquals(2 + 2 + 2 + 2 + 2, testC.length());
assertEquals(2 + 2 + 2, testE.length());
}
Recommended Posts