Bienvenido a proyecto online, en este sitio vas a encontrar la solucíon a lo que buscas.
Solución:
El modelo normal de Java string largo
String.length()
es especificado como devolviendo el número de char
valores (“unidades de código”) en la cadena. Eso es el más generalmente útil definición de la longitud de una cadena Java; vea abajo.
Tu descripción1 de la semántica de length
basado en el tamaño del respaldo array/array el corte es incorrecto. El hecho de que el valor devuelto por length()
es además el tamaño del respaldo array o array rebanada es simplemente un detalle de implementación de las típicas bibliotecas de clases de Java. String
no necesita implementarse de esa manera. De hecho, creo que he visto implementaciones de Java String donde NO FUE implementado de esa manera.
Modelos alternativos de string largo.
Para obtener el número de puntos de código Unicode en un uso de String str.codePointCount(0, str.length())
– ver el javadoc.
Para obtener el tamaño (en bytes) de una cadena en una codificación específica (es decir, juego de caracteres), use str.getBytes(charset).length
2.
Para lidiar con problemas específicos de la configuración regional, puede usar Normalizer
para normalizar la cadena a la forma que sea más apropiada para su caso de uso, y luego use codePointCount
como anteriormente. Pero en algunos casos, ni siquiera esto funcionará; por ejemplo, las reglas de conteo de letras húngaras que aparentemente el estándar Unicode no atiende.
Usar String.length () generalmente está bien
La razón por la que la mayoría de las aplicaciones usan String.length()
es que la mayoría de las aplicaciones no se preocupan por contar el número de caracteres en palabras, textos, etcétera de una manera centrada en el ser humano. Por ejemplo, si hago esto:
String s = "hi mum how are you";
int pos = s.indexOf("mum");
String textAfterMum = s.substring(pos + "mum".length());
realmente no importa eso "mum".length()
no devuelve puntos de código o que no es un recuento de caracteres lingüísticamente correcto. Está midiendo la longitud del string utilizando el modelo que sea apropiado para la tarea en cuestión. Y funciona.
Obviamente, las cosas se complican un poco más cuando se realiza un análisis de texto multilingüe; por ejemplo, buscando palabras. Pero incluso entonces, si normaliza el texto y los parámetros antes de comenzar, puede codificar con seguridad en términos de “unidades de código” en lugar de “puntos de código” la mayor parte del tiempo; es decir length()
todavía funciona.
1 – Esta descripción estaba en algunas versiones de la pregunta. Consulte el historial de edición … si tiene suficientes puntos de repetición.
2 – Utilizando str.getBytes(charset).length
implica hacer la codificación y tirarlo. Posiblemente haya un general forma de hacer esto sin esa copia. Implicaría envolver el String
como un CharBuffer
, creando un personalizado ByteBuffer
sin respaldo para actuar como un contador de bytes, y luego usando Encoder.encode(...)
para contar los bytes. Nota: No he probado esto y no recomendaría intentarlo. a no ser que tienes evidencia clara de que getBytes(charset)
es un cuello de botella significativo en el rendimiento.
java.text.BreakIterator
es capaz de iterar sobre el texto y puede informar sobre límites de “caracteres”, palabras, frases y líneas.
Considere este código:
def length(text: String, locale: java.util.Locale = java.util.Locale.ENGLISH) =
val charIterator = java.text.BreakIterator.getCharacterInstance(locale)
charIterator.setText(text)
var result = 0
while(charIterator.next() != BreakIterator.DONE) result += 1
result
Ejecutarlo:
scala> val text = "Thîs lóo̰ks we̐ird!"
text: java.lang.String = Thîs lóo̰ks we̐ird!
scala> val length = length(text)
length: Int = 17
scala> val codepoints = text.codePointCount(0, text.length)
codepoints: Int = 21
Con parejas sustitutas:
scala> val parens = "uDBFFuDFFCsurpiu0301se!uDBFFuDFFD"
parens: java.lang.String = surpíse!
scala> val length = length(parens)
length: Int = 10
scala> val codepoints = parens.codePointCount(0, parens.length)
codepoints: Int = 11
scala> val codeunits = parens.length
codeunits: Int = 13
Esto debería funcionar en la mayoría de los casos.
Depende exactamente de lo que quieras decir con “longitud de [the] Cuerda”:
String.length()
devuelve el número dechars
en elString
. Esto normalmente solo es útil para programar tareas relacionadas como la asignación de búferes porque la codificación de múltiples bytes puede causar problemas, lo que significa que unochar
no significa un punto de código Unicode.String.codePointCount(int, int)
yCharacter.codePointCount(CharSequence,int,int)
ambos devuelven el número de puntos de código Unicode en elString
. Esto normalmente sólo es útil para programar tareas relacionadas que requieren mirar unString
como una serie de puntos de código Unicode sin necesidad de preocuparse por la interferencia de codificación multibyte.BreakIterator.getCharacterInstance(Locale)
se puede utilizar para obtener el siguiente grafema en unString
por lo dadoLocale
. Usar esto varias veces puede permitirle contar el número de grafemas en unString
. Dado que los grafemas son básicamente letras (en la mayora de las circunstancias) este mtodo es til para obtener el nmero de caracteresString
contiene. Básicamente, este método devuelve aproximadamente el mismo número que obtendría si contara manualmente el número de letras en elString
, lo que lo hace útil para cosas como dimensionar interfaces de usuario y dividirStrings
sin corromper los datos.
Para darle una idea de cómo cada uno de los diferentes métodos puede devolver diferentes longitudes para los mismos datos exactos, creé esta clase para generar rápidamente las longitudes del texto Unicode contenido en esta página, que está diseñada para ofrecer una prueba completa de muchos diferentes idiomas con caracteres no ingleses. Estos son los resultados de ejecutar ese código después de normalizar el archivo de entrada de tres formas diferentes (sin normalización, NFC, NFD):
Input UTF-8 String
>> String.length() = 3431
>> String.codePointCount(int,int) = 3431
>> BreakIterator.getCharacterInstance(Locale) = 3386
NFC Normalized UTF-8 String
>> String.length() = 3431
>> String.codePointCount(int,int) = 3431
>> BreakIterator.getCharacterInstance(Locale) = 3386
NFD Normalized UTF-8 String
>> String.length() = 3554
>> String.codePointCount(int,int) = 3554
>> BreakIterator.getCharacterInstance(Locale) = 3386
Como puede ver, incluso el “mismo aspecto” String
podría dar resultados diferentes para la longitud si usa String.length()
o String.codePointCount(int,int)
.
Para obtener más información sobre este tema y otros temas similares, debe leer esta publicación de blog que cubre una variedad de conceptos básicos sobre el uso de Java para manejar correctamente Unicode.