example - getbytes java
¿Cómo puedo iterar a través de los puntos de código Unicode de Java String? (4)
Así que sé sobre String#codePointAt(int)
, pero está indexado por el desplazamiento de char
, no por el desplazamiento del punto de código.
Estoy pensando en probar algo como:
- usando
String#charAt(int)
para obtener elchar
en un índice - probando si el
char
está en el rango de sustitutos altos- si es así, use
String#codePointAt(int)
para obtener el punto de código e incremente el índice en 2 - si no, use el valor
char
dado como el punto de código, e incremente el índice en 1
- si es así, use
Pero mis preocupaciones son
- No estoy seguro de si los puntos de código que están naturalmente en el rango de sustitutos altos se almacenarán como dos valores de
char
o uno - esto parece una forma tremendamente cara de iterar a través de los personajes
- alguien debe haber encontrado algo mejor.
Java 8 agregó CharSequence#codePoints
que devuelve un IntStream
contiene los puntos de código. Puede usar la secuencia directamente para iterar sobre ellos:
string.codePoints().forEach(c -> ...);
o con un bucle for al recopilar la secuencia en una matriz:
for(int c : string.codePoints().toArray()){
...
}
Estas formas son probablemente más costosas que la solución de Jonathan Feinbergs , pero son más rápidas de leer / escribir y la diferencia de rendimiento generalmente será insignificante.
La iteración de puntos de código se archiva como solicitud de función en Sun.
También hay un ejemplo sobre cómo iterar sobre los CodePoints de cadena allí.
Pensé que agregaría un método alternativo que funciona con los bucles foreach ( ref ), además de que puedes convertirlo al nuevo método String # codePoints de java 8 fácilmente cuando te muevas a java 8:
public static Iterable<Integer> codePoints(final String string) {
return new Iterable<Integer>() {
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
int nextIndex = 0;
public boolean hasNext() {
return nextIndex < string.length();
}
public Integer next() {
int result = string.codePointAt(nextIndex);
nextIndex += Character.charCount(result);
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
}
Entonces puedes usarlo con foreach como este:
for(int codePoint : codePoints(myString)) {
....
}
O alternativamente, si solo desea convertir una cadena en una matriz de int (que podría usar más RAM que el enfoque anterior):
public static List<Integer> stringToCodePoints(String in) {
if( in == null)
throw new NullPointerException("got null");
List<Integer> out = new ArrayList<Integer>();
final int length = in.length();
for (int offset = 0; offset < length; ) {
final int codepoint = in.codePointAt(offset);
out.add(codepoint);
offset += Character.charCount(codepoint);
}
return out;
}
Sí, Java usa una codificación UTF-16-esque para representaciones internas de cadenas, y, sí, codifica caracteres fuera del plano multilingüe básico ( BMP ) utilizando el esquema de subrogación.
Si sabe que tratará con caracteres que están fuera del BMP, esta es la manera canónica de iterar sobre los caracteres de un Java String:
final int length = s.length();
for (int offset = 0; offset < length; ) {
final int codepoint = s.codePointAt(offset);
// do something with the codepoint
offset += Character.charCount(codepoint);
}