Recorte una cadena según la longitud de la cadena

136

Quiero recortar una cadena si la longitud supera los 10 caracteres.

Suponga que si la longitud de la cadena es 12 ( String s="abcdafghijkl"), la nueva cadena recortada contendrá "abcdefgh..".

¿Cómo puedo conseguir esto?

yshak
fuente
66
posible duplicado de hasta los primeros N caracteres
Stephen C
Para su información, una ELLIPSIS HORIZONTAL es un solo carácter, no dos o tres caracteres de PARADA COMPLETA : ...
Basil Bourque

Respuestas:

262
s = s.substring(0, Math.min(s.length(), 10));

Usar Math.minasí evita una excepción en el caso de que la cadena ya sea más corta que 10.


Notas:

  1. Lo anterior hace un recorte real. Si realmente desea reemplazar los últimos tres (!) Caracteres con puntos si se trunca, use Apache Commons StringUtils.abbreviate.

  2. Esto puede comportarse incorrectamente 1 si su Cadena contiene puntos de código Unicode fuera del BMP; Ej. Emojis. Para obtener una solución (más complicada) que funcione correctamente para todos los puntos de código Unicode, consulte la solución de @ sibnick .


1 - Un punto de código Unicode que no está en el plano 0 (el BMP) se representa como un "par sustituto" (es decir, dos charvalores) en el String. Al ignorar esto, podríamos recortar a menos de 10 puntos de código, o (peor) truncar en el medio de un par sustituto. Por otro lado, String.length()ya no es una medida ideal de la longitud del texto Unicode, por lo que puede ser incorrecto recortar en función de ello.

Stephen C
fuente
En lugar de Math.min, ¿no podemos hacer una verificación condicional y hacer una subcadena solo si la cadena es máxima? por ejemplo:s = (s.length() > 10) ? s.substring(0,10) : s ;
RRAM
1
Sí por supuesto que puedes. ¡Lea las otras respuestas para conocer otras formas de resolver el problema!
Stephen C
132

StringUtils.abbreviatede la biblioteca Lang de Apache Commons podría ser tu amigo:

StringUtils.abbreviate("abcdefg", 6) = "abc..."
StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
StringUtils.abbreviate("abcdefg", 4) = "a..."

Commons Lang3 incluso permite establecer una cadena personalizada como marcador de reemplazo. Con esto, por ejemplo, puede establecer puntos suspensivos de un solo carácter.

StringUtils.abbreviate("abcdefg", "\u2026", 6) = "abcde…"
H6.
fuente
55
Podría ser, pero la pregunta del OP no pide "puntos suspensivos".
Stephen C
9
@StephenC: la pregunta muestra 8 caracteres seguidos de 2 puntos, dado un límite de longitud de 10, que se parece mucho a los puntos suspensivos (solo 2 puntos en lugar de 3). También es probable que muchas de las personas que encuentran esta pregunta consideren útil una elipsis.
ToolmakerSteve
12
... y si no quieres los puntos suspensivos, StringUtils.left () puede ayudarte.
Superole
1
FYI, una ELLIPSIS HORIZONTAL es un solo personaje, no tres personajes de PARADA COMPLETA : ...
Basil Bourque
53

Hay una StringUtilsfunción de Apache Commons que hace esto.

s = StringUtils.left(s, 10)

Si los caracteres len no están disponibles, o la cadena es nula, la cadena se devolverá sin una excepción. Se devuelve una cadena vacía si len es negativo.

StringUtils.left (null, ) = nulo
StringUtils.left (
, -ve) = ""
StringUtils.left ("", *) = ""
StringUtils.left ("abc", 0) = ""
StringUtils.left (" abc ", 2) =" ab "
StringUtils.left (" abc ", 4) =" abc "

StringUtils.Left JavaDocs

Cortesía: Steeve McCauley

Mulki
fuente
22

Como de costumbre, a nadie le importan los pares sustitutos de UTF-16. Vea sobre ellos: ¿Cuáles son los caracteres Unicode no BMP más comunes en uso real? Incluso autores de org.apache.commons / commons-lang3

Puede ver la diferencia entre el código correcto y el código habitual en este ejemplo:

public static void main(String[] args) {
    //string with FACE WITH TEARS OF JOY symbol
    String s = "abcdafghi\uD83D\uDE02cdefg";
    int maxWidth = 10;
    System.out.println(s);
    //do not care about UTF-16 surrogate pairs
    System.out.println(s.substring(0, Math.min(s.length(), maxWidth)));
    //correctly process UTF-16 surrogate pairs
    if(s.length()>maxWidth){
        int correctedMaxWidth = (Character.isLowSurrogate(s.charAt(maxWidth)))&&maxWidth>0 ? maxWidth-1 : maxWidth;
        System.out.println(s.substring(0, Math.min(s.length(), correctedMaxWidth)));
    }
}
sibnick
fuente
1
Encontró el error en jira de Apache commons: issues.apache.org/jira/browse/LANG-1343
Ryan Quinn
10

s = s.length() > 10 ? s.substring(0, 9) : s;

shift66
fuente
16
El segundo parámetro de subcadena es exclusivo, por lo que esta respuesta recorta la cadena a 9 caracteres.
emulcahy
8

O simplemente puede usar este método en caso de que no tenga StringUtils a mano:

public static String abbreviateString(String input, int maxLength) {
    if (input.length() <= maxLength) 
        return input;
    else 
        return input.substring(0, maxLength-2) + "..";
}
MVojtkovszky
fuente
Tu código no funcionó para mí. Prueba estoSystem.out.println(abbreviateString("ABC\ud83d\udc3bDEF", 6));
T3rm1
4

En caso de que esté buscando una forma de recortar y mantener los ÚLTIMOS 10 caracteres de una cadena.

s = s.substring(Math.max(s.length(),10) - 10);
rekotc
fuente
3

Con Kotlin es tan simple como:

yourString.take(10)

Devuelve una cadena que contiene los primeros n caracteres de esta cadena, o la cadena completa si esta cadena es más corta.

Documentación

Leo Droidcoder
fuente
1

tl; dr

Parece que está pidiendo un carácter de puntos suspensivos ( ) en último lugar, cuando se trunca. Aquí hay una línea para manipular su cadena de entrada.

String input = "abcdefghijkl";
String output = ( input.length () > 10 ) ? input.substring ( 0 , 10 - 1 ).concat ( "…" ) : input;

Vea este código en vivo en IdeOne.com.

abcdefghi ...

Operador ternario

Podemos hacer una línea usando el operador ternario .

String input = "abcdefghijkl" ;

String output = 
    ( input.length() > 10 )          // If too long…
    ?                                
    input     
    .substring( 0 , 10 - 1 )         // Take just the first part, adjusting by 1 to replace that last character with an ellipsis.
    .concat( "…" )                   // Add the ellipsis character.
    :                                // Or, if not too long…
    input                            // Just return original string.
;

Vea este código en vivo en IdeOne.com.

abcdefghi ...

Flujos de Java

La instalación de Java Streams lo hace interesante, a partir de Java 9 y posterior. Interesante, pero quizás no sea el mejor enfoque.

Usamos puntos de código en lugar de charvalores. El chartipo es heredado y está limitado al subconjunto de todos los posibles caracteres Unicode .

String input = "abcdefghijkl" ;
int limit = 10 ;
String output =
        input
                .codePoints()
                .limit( limit )
                .collect(                                    // Collect the results of processing each code point.
                        StringBuilder::new,                  // Supplier<R> supplier
                        StringBuilder::appendCodePoint,      // ObjIntConsumer<R> accumulator
                        StringBuilder::append                // BiConsumer<R,​R> combiner
                )
                .toString()
        ;

Si tuvimos caracteres en exceso truncados, reemplace el último carácter con puntos suspensivos .

if ( input.length () > limit )
{
    output = output.substring ( 0 , output.length () - 1 ) + "…";
}

Si tan solo pudiera pensar en una forma de juntar la línea de transmisión con la parte "si está por encima del límite, elípticos".

Albahaca Bourque
fuente
No. Claramente, quiere recortar la longitud de la cuerda si alcanza una longitud de 11 o más. Debe estar trabajando en un nuevo sistema de IA oO
JD333
1
@ JD333 Tu comentario se me escapa. Truncar a una longitud de 10 incluyendo los puntos suspensivos es exactamente lo que muestro aquí.
Basil Bourque
0
str==null ? str : str.substring(0, Math.min(str.length(), 10))

o,

str==null ? "" : str.substring(0, Math.min(str.length(), 10))

Funciona con nulo.

aceminds
fuente