Sie berechnen die UTF-8
Länge schnell
public static int utf8Length(CharSequence cs) {
return cs.codePoints()
.map(cp -> cp<=0x7ff? cp<=0x7f? 1: 2: cp<=0xffff? 3: 4)
.sum();
}
mit der Wenn ASCII-Zeichen die Inhalte dominieren, könnte es etwas schneller zu bedienen
public static int utf8Length(CharSequence cs) {
return cs.length()
+ cs.codePoints().filter(cp -> cp>0x7f).map(cp -> cp<=0x7ff? 1: 2).sum();
}
statt.
Sie können aber auch das Optimierungspotenzial der nicht die gesamte Größe neu zu berechnen, sondern nur um die Größe des neuen Fragments betrachten Sie die StringBuilder
sind Anfügen etwas gleich
StringBuilder sb = new StringBuilder();
int length = 0;
for(…; …; …) {
String s = … //calculateNextString();
sb.append(s);
length += utf8Length(s);
if(length >= 5242880) {
// Do something
// in case you're flushing the data:
sb.setLength(0);
length = 0;
}
}
Dies setzt voraus, dass, wenn Sie‘ wenn Fragmente mit Ersatzpaaren angehängt werden, sind sie immer vollständig und nicht in ihre Hälften geteilt. Für normale Anwendungen sollte dies immer der Fall sein.
Eine weitere Möglichkeit, durch Didier-L vorgeschlagen, ist die Berechnung zu verschieben, bis Ihre StringBuilder
eine Länge der durch drei geteilt Schwelle erreicht, nach wie vor, dass es unmöglich ist, eine UTF-8
Länge größer als die Schwelle zu haben. Dies wird jedoch nur dann von Vorteil sein, wenn Sie in einigen Ausführungen threshold/3
nicht erreichen.
Als weitere Optimierung, da ein Zeichen höchstens 3 Bytes benötigt, könnten Sie auch vermeiden, die Länge zu berechnen, bis die 'StringBuilder'-Länge 5MB/3 erreicht. –
@Holger In jdk-9 gibt es 'String :: codePoints', die den Unterschied zwischen ASCII- und Nicht-ASCII-Strings ausmachen ... Auch diese Technik funktioniert nur für UTF-8, es ist immer noch nett. – Eugene
@Eugene: Die Berechnung der 'UTF-8'-Länge ist der einzige Zweck dieser Übung. Abgesehen davon wird die Implementierung von 'codePoints()' in Java 9 für diese Antwort keinen Unterschied machen. Der Unterschied zwischen den beiden Lösungen dieser Antwort besteht darin, dass die zweite nur eine Bedingung für ASCII-Zeichen ausführt und die Additionsoperation überspringt. Nach der Behebung eines Fehlers unterscheiden sich die beiden Varianten im Worst-Case nicht mehr, so gewinnt immer der 2.. Eine billige "isAllASCII" -Methode wäre hilfreich, aber soweit ich weiß, wird Java 9 intern nur zwischen iso-latin-1 und anderen Strings unterscheiden. – Holger