web-dev-qa-db-fra.com

Sous-chaîne Java: 'index de chaîne hors de portée'

Je suppose que je reçois cette erreur car la chaîne tente de sous-chaîne d'une valeur null. Mais la partie ".length() > 0" n'éliminerait-elle pas ce problème?

Voici l'extrait de code Java:

if (itemdescription.length() > 0) {
    pstmt2.setString(3, itemdescription.substring(0,38));
} 
else { 
    pstmt2.setString(3, "_");
} 

J'ai eu cette erreur: 

 Java.lang.StringIndexOutOfBoundsException: String index out of range: 38
    at Java.lang.String.substring(Unknown Source)
    at MASInsert2.itemimport(MASInsert2.Java:192)
    at MASInsert2.processRequest(MASInsert2.Java:125)
    at MASInsert2.doGet(MASInsert2.Java:219)
    at javax.servlet.http.HttpServlet.service(HttpServlet.Java:627)
    at javax.servlet.http.HttpServlet.service(HttpServlet.Java:729)
    at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:269)
    at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:188)
    at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:213)
    at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:172)
    at org.Apache.catalina.core.StandardHostValve.invoke(StandardHostValve.Java:127)
    at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:117)
    at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:108)
    at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:174)
    at org.Apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.Java:835)
    at org.Apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.Java:640)
    at org.Apache.Tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.Java:1286)
    at Java.lang.Thread.run(Unknown Source)
17
phill

"Je suppose que je reçois cette erreur Parce que la chaîne tente de Sous-chaîne une valeur Null. Mais ne le ferait pas La partie" .length ()> 0 "éliminerait Ce problème ?

Non, appeler itemdescription.length () lorsque itemdescription est nul ne générerait pas une exception StringIndexOutOfBoundsException, mais plutôt une exception NullPointerException car vous essaieriez essentiellement d'appeler une méthode sur null .

Comme d'autres l'ont indiqué, StringIndexOutOfBoundsException indique que la description d'un article ne fait pas au moins 38 caractères. Vous voulez probablement gérer les deux conditions (je suppose que vous voulez tronquer):

final String value;
if (itemdescription == null || itemdescription.length() <= 0) {
    value = "_";
} else if (itemdescription.length() <= 38) {
    value = itemdescription;
} else { 
    value = itemdescription.substring(0, 38);
}
pstmt2.setString(3, value);

Peut-être un bon endroit pour une fonction utilitaire si vous le faites souvent ...

31
Bert F

Il est dommage que substring ne soit pas implémenté de manière à gérer des chaînes courtes - comme dans d’autres langues, par exemple. Python.

Ok, nous ne pouvons pas changer cela et devons considérer ce cas Edge chaque fois que nous utilisons substr, au lieu des clauses if-else, je choisirais cette variante plus courte:

myText.substring(0, Math.min(6, myText.length()))
22
linqu

Vous devez vraiment vérifier si la longueur de la chaîne est supérieure ou égale à 38.

9
Jase Whatson

Je recommanderais Apache commons lang . Un one-liner prend en charge le problème.

pstmt2.setString(3, StringUtils.defaultIfEmpty(
    StringUtils.subString(itemdescription,0, 38), "_")); 
6

substring(0,38) signifie que la chaîne doit être composée de 38 caractères ou plus. Sinon, "l'index de chaîne est hors de portée".

4
Apocalisp
if (itemdescription != null && itemdescription.length() > 0) {
    pstmt2.setString(3, itemdescription.substring(0, Math.min(itemdescription.length(), 38))); 
} else { 
    pstmt2.setString(3, "_"); 
}
4
JeeBee

Je suppose que votre colonne contient 38 caractères, vous voulez donc tronqueritemdescription pour tenir dans la base. Une fonction utilitaire comme celle-ci devrait faire ce que vous voulez:

/**
 * Truncates s to fit within len. If s is null, null is returned.
 **/
public String truncate(String s, int len) { 
  if (s == null) return null;
  return s.substring(0, Math.min(len, s.length()));
}

alors vous appelez juste comme ça:

String value = "_";
if (itemdescription != null && itemdescription.length() > 0) {
  value = truncate(itemdescription, 38);
}

pstmt2.setString(3, value);
2
Chris Gow

La méthode substring de Java échoue lorsque vous essayez d'obtenir une sous-chaîne commençant à un index plus long que la chaîne.

Une alternative simple consiste à utiliser Apache Commons StringUtils.substring :

public static String substring(String str, int start)

Gets a substring from the specified String avoiding exceptions.

A negative start position can be used to start n characters from the end of the String.

A null String will return null. An empty ("") String will return "".

 StringUtils.substring(null, *)   = null
 StringUtils.substring("", *)     = ""
 StringUtils.substring("abc", 0)  = "abc"
 StringUtils.substring("abc", 2)  = "c"
 StringUtils.substring("abc", 4)  = ""
 StringUtils.substring("abc", -2) = "bc"
 StringUtils.substring("abc", -4) = "abc"

Parameters:
str - the String to get the substring from, may be null
start - the position to start from, negative means count back from the end of the String by this many characters

Returns:
substring from start position, null if null String input

Notez que si vous ne pouvez pas utiliser Apache Commons lib pour une raison quelconque, vous pouvez simplement récupérer les parties dont vous avez besoin à la source

// Substring
//-----------------------------------------------------------------------
/**
 * <p>Gets a substring from the specified String avoiding exceptions.</p>
 *
 * <p>A negative start position can be used to start {@code n}
 * characters from the end of the String.</p>
 *
 * <p>A {@code null} String will return {@code null}.
 * An empty ("") String will return "".</p>
 *
 * <pre>
 * StringUtils.substring(null, *)   = null
 * StringUtils.substring("", *)     = ""
 * StringUtils.substring("abc", 0)  = "abc"
 * StringUtils.substring("abc", 2)  = "c"
 * StringUtils.substring("abc", 4)  = ""
 * StringUtils.substring("abc", -2) = "bc"
 * StringUtils.substring("abc", -4) = "abc"
 * </pre>
 *
 * @param str  the String to get the substring from, may be null
 * @param start  the position to start from, negative means
 *  count back from the end of the String by this many characters
 * @return substring from start position, {@code null} if null String input
 */
public static String substring(final String str, int start) {
    if (str == null) {
        return null;
    }

    // handle negatives, which means last n characters
    if (start < 0) {
        start = str.length() + start; // remember start is negative
    }

    if (start < 0) {
        start = 0;
    }
    if (start > str.length()) {
        return EMPTY;
    }

    return str.substring(start);
}
2
Brad Parks

itemdescription est inférieur à 38 caractères. C’est pourquoi la variable StringOutOfBoundsException est lancée.

La vérification de .length() > 0 s'assure simplement que la String a une valeur non nulle, ce que vous devez faire est de vérifier que sa longueur est suffisante Tu pourrais essayer:

if(itemdescription.length() > 38)
  ...
1
pugmarx

Vous devez vérifier la longueur de la chaîne. Vous supposez que vous pouvez faire substring(0,38) tant que String n'est pas null, mais vous avez en fait besoin que String ait au moins 38 caractères.

0
sixtytrees