Find out number of characters in a UTF-8 string in Java/Android
The shortest "length" is in Unicode code points, as notion of numbered character, UTF-32.
Correction: As @liudongmiao mentioned probably one should use:
int length = string.codePointCount(0, s.length);
In java 8:
int length = (int) string.codePoints().count();
Prior javas:
int length(String s) {
int n = 0;
for (int i = 0; i < s.length(); ++n) {
int cp = s.codePointAt(i);
i += Character.charCount(cp);
}
return n;
}
A Unicode code point can be encoded in UTF-16 as one or two char
s.
The same Unicode character might have diacritical marks. They can be written as separate code points: basic letter + zero or more diacritical marks. To normalize the string to one (C=) compressed code point:
string = java.text.Normalizer.normalize(string, Normalizer.Form.NFC);
BTW for database purposes, the UTF-16 length seems more useful:
string.length() // Number of UTF-16 chars, every char two bytes.
(In the example mentioned UTF-32 length == UTF-16 length.)
A dump function
A commenter had some unexpected result:
void dump(String s) {
int n = 0;
for (int i = 0; i < s.length(); ++n) {
int cp = s.codePointAt(i);
int bytes = Character.charCount(cp);
i += bytes;
System.out.printf("[%d] #%dB: U+%X = %s%n",
n, bytes, cp, Character.getName(cp));
}
System.out.printf("Length:%d%n", n);
}
Take a look at the http://rosettacode.org/wiki/String_length#Grapheme_Length_4:
import java.text.BreakIterator;
public class Grapheme {
public static void main(String[] args) {
printLength("møøse");
printLength("");
printLength("J̲o̲s̲é̲");
}
public static void printLength(String s) {
BreakIterator it = BreakIterator.getCharacterInstance();
it.setText(s);
int count = 0;
while (it.next() != BreakIterator.DONE) {
count++;
}
System.out.println("Grapheme length: " + count+ " " + s);
}
}
Output:
Grapheme length: 5 møøse
Grapheme length: 7
Grapheme length: 4 J̲o̲s̲é̲
What you are looking for is not string length bu grapeme length. It gives you the number of "visible" characters.
String.length()
actually returns the number of characters in a string encoded in UTF-16 (where two bytes are used to encode a character). However this should work for most UTF-8 chars too unless you have a character with an ASCII value greater than 127. If you want to do things by hand without encoding it to UTF-8, you can do something like this
public static int utf8Length(CharSequence sequence) {
int count = 0;
for (int i = 0; i < sequence.length(); i++) {
char ch = sequence.charAt(i);
if (ch <= 0x7F) {
count++;
} else if (ch <= 0x7FF) {
count += 2;
} else if (Character.isHighSurrogate(ch)) {
count += 4;
++i;
} else {
count += 3;
}
}
return count;
}
Here's the UTF-8 spec.