Подстрока Java: «строковый индекс вне диапазона» - PullRequest
18 голосов
/ 05 июня 2009

Я предполагаю, что получаю эту ошибку, потому что строка пытается подставить значение null. Но не устранит ли проблема ".length() > 0" эту проблему?

Вот фрагмент кода Java:

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

Я получил эту ошибку:

 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)

Ответы [ 12 ]

32 голосов
/ 05 июня 2009

Я предполагаю, что получаю эту ошибку потому что строка пытается подстрока нулевое значение. Но не будет часть ".length ()> 0" исключает этот вопрос?

Нет, вызов itemdescription.length (), когда itemdescription имеет значение null, не будет генерировать исключение StringIndexOutOfBoundsException, а скорее NullPointerException, поскольку вы по сути пытаетесь вызвать метод для null .

Как указали другие, StringIndexOutOfBoundsException указывает, что длина описания элемента не менее 38 символов. Вы, вероятно, хотите обработать оба условия (я предполагаю, что вы хотите усечь):

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);

Может быть хорошим местом для функции полезности, если вы делаете это много ...

23 голосов
/ 12 марта 2014

Жаль, что substring не реализован так, чтобы обрабатывать короткие строки - как в других языках, например Python.

Хорошо, мы не можем это изменить и должны рассматривать этот крайний случай каждый раз, когда мы используем substr, вместо предложений if-else я бы выбрал этот более короткий вариант:

myText.substring(0, Math.min(6, myText.length()))
9 голосов
/ 05 июня 2009

Вам действительно нужно проверить, больше ли длина строки или равна 38.

6 голосов
/ 05 июня 2009

Я бы порекомендовал apache commons lang . Однострочник решает проблему.

pstmt2.setString(3, StringUtils.defaultIfEmpty(
    StringUtils.subString(itemdescription,0, 38), "_")); 
5 голосов
/ 05 июня 2009
if (itemdescription != null && itemdescription.length() > 0) {
    pstmt2.setString(3, itemdescription.substring(0, Math.min(itemdescription.length(), 38))); 
} else { 
    pstmt2.setString(3, "_"); 
}
5 голосов
/ 05 июня 2009

substring(0,38) означает, что строка должна быть длиной не более 38 символов. В противном случае «Строковый индекс выходит за пределы диапазона».

2 голосов
/ 17 августа 2016

Метод Java substring завершается неудачно, когда вы пытаетесь получить подстроку, начинающуюся с индекса, который длиннее строки.

Легкой альтернативой является использование 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

Обратите внимание: если по какой-то причине вы не можете использовать Apache Commons lib, вы можете просто получить нужные вам части из источника

<code>// 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"
 * 
* * @param str String для получения подстроки, может быть нулевым * @param start позиция для начала, отрицательное значение * отсчитывать от конца строки по этому количеству символов * @ возвратить подстроку из начальной позиции, {@code null}, если нулевой ввод String * / public static String подстрока (final String str, int start) { if (str == null) { вернуть ноль; } // обрабатывать негативы, что означает последние n символов if (start <0) { start = str.length () + start; // помните начало отрицательно } if (start <0) { начало = 0; } if (start> str.length ()) { вернуть ПУСТОЙ; } вернуть str.substring (начало); }
2 голосов
/ 05 июня 2009

Я предполагаю, что ваш столбец имеет длину 38 символов, поэтому вы хотите усечь itemdescription, чтобы поместиться в базу данных. Служебная функция, подобная следующей, должна делать то, что вы хотите:

/**
 * 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()));
}

тогда вы просто называете это так:

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

pstmt2.setString(3, value);
1 голос
/ 05 июня 2009

itemdescription меньше 38 символов. Вот почему StringOutOfBoundsException выбрасывается.

Проверка .length() > 0 просто удостоверяется, что String имеет некоторое ненулевое значение, и вам нужно проверить, что длина достаточно велика. Вы можете попробовать:

if(itemdescription.length() > 38)
  ...
0 голосов
/ 26 апреля 2019

Когда это уместно, я использую совпадения вместо подстрока .

С подстрокой :

if( myString.substring(1,17).equals("Someting I expect") ) {
    // Do stuff
}
// Does NOT work if myString is too short

При совпадениях (необходимо использовать обозначение Regex):

if( myString.matches("Someting I expect.*") ) {
    // Do stuff
}
// This works with all strings
...