2009-10-18 11 views
104

¿Cómo puedo obtener hasta los primeros caracteres n de una cadena en Java sin hacer una verificación de tamaño primero (en línea es aceptable) o poner en riesgo un IndexOutOfBoundsException?¿Cómo obtengo los primeros n caracteres de una cadena sin verificar el tamaño o salir de los límites?

+1

a menos que coger la excepción, no sé cómo va a manejar el caso en el que la longitud de caracteres es mayor que la longitud de cadena. –

+2

¿Por qué? ¿Cuál es su aversión a verificar la longitud o atrapar una excepción? – paxdiablo

+1

Por curiosidad, ¿por qué quieres evitar la verificación de tamaño? Esto no es C. –

Respuesta

258

Aquí hay una solución clara y simple:

String upToNCharacters = s.substring(0, Math.min(s.length(), n)); 

Opinión: mientras que esta solución es "limpio", creo que es en realidad menos legible que una solución que utiliza if/else en lo obvio camino. Si el lector no ha visto este truco, tiene que pensar más difícil para comprender el código. IMO, el significado del código es más obvio en la versión if/else.

+1

Un poco fuera de tema, pero si/cuando tiene la opción de usar Groovy 1.8+, puede usar el método take (int). –

+0

+1. Aún mejor si esto está envuelto en una función llamada safe_substring o substring_safe, como la respuesta de paxdiablo, por lo que el uso es más fácil de leer/intento más obvio. – ToolmakerSteve

+2

iba a proponer ** s.length() AxelH

4

utilizar el método de subcadena, de la siguiente manera:

int n = 8; 
String s = "Hello, World!"; 
System.out.println(s.substring(0,n); 

Si n es mayor que la longitud de la cadena, esto va a lanzar una excepción, como un comentarista ha señalado. Una solución simple es envolver todo esto en la condición if(s.length()<n) en su cláusula else, puede elegir si desea imprimir/devolver todo el String o manejarlo de otra manera.

+1

esto corre el riesgo de obtener una excepción IndexOutOfBoundsException –

+0

Por cierto, si planea programar en Java, debe intentar memorizar la mayoría de los métodos API para String (http://java.sun.com/j2se/1.5.0/docs/ api/java/lang/String.html). –

+0

Ya he descartado la subcadena, al menos en sí misma, como _no_ la respuesta. –

12

Hay una clase de pregunta en tanto que a veces hacer menos de sentido, éste es peligrosamente cerca :-)

Tal vez podría explicar su aversión a la utilización de uno de los dos métodos que se descartó.

Si es sólo porque usted no desea la pimienta el código con if declaraciones o código de captura de excepción, una solución es utilizar una función de ayuda que se hará cargo de él para usted, algo así como:

static String substring_safe (String s, int start, int len) { ... } 

que verificará las longitudes de antemano y actuará en consecuencia (o devuelva una cuerda más pequeña o una almohadilla con espacios).

Entonces usted no tiene que preocuparse por ello en su código en absoluto, simplemente llame a:

String s2 = substring_safe (s, 10, 7); 

en lugar de:

String s2 = s.substring (10,7); 

esto funcionaría en el caso de que usted parece preocúpese (en función de sus comentarios por otras respuestas), no rompa el flujo del código cuando haga muchas cosas para construir cuerdas.

+1

Deberías leer el comentario más de cerca, @antony, especialmente el emoticón, y no ser tan valioso para aquellos que intentan ayudar. Me limité a decir que no le había explicado por qué tenía que evitar los dos métodos. Y esta es una respuesta genuina, usando una función de ayuda, que es por lo que no está en un comentario. – paxdiablo

+1

+1: Este es un enfoque MUCHO mejor que el aceptado, dado el deseo de OP de no saturar el código. (o vea la solución de Nickkk de incluir una biblioteca que ya tiene una función que se comporta como se desea). – ToolmakerSteve

52

No reinventar la rueda ...:

org.apache.commons.lang.StringUtils.substring(String s, int start, int len) 

Javadoc dice:

StringUtils.substring(null, *, *) = null 
StringUtils.substring("", * , *) = ""; 
StringUtils.substring("abc", 0, 2) = "ab" 
StringUtils.substring("abc", 2, 0) = "" 
StringUtils.substring("abc", 2, 4) = "c" 
StringUtils.substring("abc", 4, 6) = "" 
StringUtils.substring("abc", 2, 2) = "" 
StringUtils.substring("abc", -2, -1) = "b" 
StringUtils.substring("abc", -4, 2) = "ab" 

Por lo tanto:

StringUtils.substring("abc", 0, 4) = "abc" 
+1

No responde la pregunta, pero independientemente de eso, aún proporciona la solución. Si el OP es capaz de entender, creo que esta es una mejor solución. – AUllah1

+3

También podría ser útil señalar que 'StringUtils.substring (yourString, 0, n)' no es lo mismo que 'yourString.substring (0, n)'. El primero es de 'StringUtils', mientras que el último usa' String.substring' (que da una excepción si el índice final excede la longitud de la cadena). – ToolmakerSteve

+0

Al igual que FYI, si busca en el código fuente de este método, maneja el caso donde el extremo es mayor que la longitud al cambiar el final por la longitud: 'if (end> str.length()) {end = str.length();} ' – bholl

6
String upToNCharacters = String.format("%."+ n +"s", str); 

horrible si n es una variable (por lo que debe construir la cadena de formato), pero bastante claro si una constante:

String upToNCharacters = String.format("%.10s", str); 

docs

+0

Alternativa interesante, aunque no puedo imaginar usarla alguna vez, dados los enfoques más tradicionales, que se dieron hace cuatro años. – ToolmakerSteve

-1

Apache Commons me sorprendieron, StringUtils.abbreviate(String str, int maxWidth) anexa "..." no hay ninguna opción para cambiar de sufijo. WordUtils.abbreviate(String str, int lower, int upper, String appendToEnd) busca en el siguiente espacio vacío.

sólo voy a dejar esto aquí:

public static String abbreviate(String s, int maxLength, String appendToEnd) { 
    String result = s; 
    appendToEnd = appendToEnd == null ? "" : appendToEnd; 
    if (maxLength >= appendToEnd.length()) { 
     if (s.length()>maxLength) { 
      result = s.substring(0, Math.min(s.length(), maxLength - appendToEnd.length())) + appendToEnd; 
     } 
    } else { 
     throw new StringIndexOutOfBoundsException("maxLength can not be smaller than appendToEnd parameter length."); 
    } 
    return result; 
} 
Cuestiones relacionadas