Saltar al contenido

¿Cómo calcular correctamente la longitud de una cadena en Java?

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).length2.

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 de chars en el String. 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 uno char no significa un punto de código Unicode.
  • String.codePointCount(int, int) y Character.codePointCount(CharSequence,int,int) ambos devuelven el número de puntos de código Unicode en el String. Esto normalmente sólo es útil para programar tareas relacionadas que requieren mirar un String 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 un String por lo dado Locale. Usar esto varias veces puede permitirle contar el número de grafemas en un String. Dado que los grafemas son básicamente letras (en la mayora de las circunstancias) este mtodo es til para obtener el nmero de caracteres String contiene. Básicamente, este método devuelve aproximadamente el mismo número que obtendría si contara manualmente el número de letras en el String, lo que lo hace útil para cosas como dimensionar interfaces de usuario y dividir Strings 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.

Aquí puedes ver las comentarios y valoraciones de los usuarios

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *