XML结束标签解析异常求助:StringIndexOutOfBoundsException排查
解析XML时的StringIndexOutOfBoundsException问题
问题场景
要解析的XML单行内容如下:
<Index>1</Index><Price>$18.38</Price><Product>Takis Fuego, 1 Ounce (46 Pack)</Product><SoldBy> Sam's Club</SoldBy><href>https://www.google.com/shopping/product/14559077146163012667?hl=en&sxsrf=ALiCzsb1Gfl32-pXt32h0QkkE-T57FtdxA:1670964406762&psb=1&q=takis&prds=eto:15330784880350744537_0,pid:15387764403936018691,rsk:PC_15179594788466925291&sa=X&ved=0ahUKEwjPgJuOvsj-AhUJGlkFHSQsBpcQ8gIIpgooAA</href>
运行解析代码时触发以下异常:
java.lang.StringIndexOutOfBoundsException: begin 6, end -1, length 355 at java.base/java.lang.String.checkBoundsBeginEnd(String.java:4601) at java.base/java.lang.String.substring(String.java:2704) at SeerWebCrawler.buildGUIFile(SeerWebCrawler.java:133) at SeerWebCrawler.main(SeerWebCrawler.java:58)
相关代码
解析XML的代码
private static void buildGUIFile() throws IOException { List<String> fileLines = Files.readAllLines(fileName); for (int i = 0; i < (fileLines.size()); i++) { resNum = i + 1; int beginIndex = fileLines.indexOf("<Price>"); int endIndex = fileLines.indexOf("</Price>"); try { price = fileLines.get(i).trim().substring(fileLines.indexOf("<Price>".trim()) + "<Price>".trim().length(), fileLines.indexOf("</Price>".trim())); } catch (StringIndexOutOfBoundsException e) { System.out.println("endIndex" + endIndex); e.printStackTrace(); } } }
生成XML格式的代码
public String xmlString() { String str = "<Index>" + resultNum + "</Index>" + "<Price>" + Price + "</Price>" + "<Product>" + Product + "</Product>" + "<SoldBy> " + Company + "</SoldBy>" + "<href>" + link + "</href>"; return str; }
问题原因
异常里的end -1直接暴露了核心问题:
- 混淆List与String的indexOf方法:你调用的
fileLines.indexOf("<Price>")是在List<String>中查找**完整等于"
"元素,因此return (<Price>"的元素索引**,而非在当前循环的行字符串中查找子串位置。由于你的XML是单行完整结构,List中不存在单独的"<Price>"或"</Price>)fileLines.indexOf("</Price>")返回-1。 - substring参数非法:当把-1作为结束索引传入
substring时,必然触发StringIndexOutOfBoundsException,因为结束索引不能小于开始索引。
修复方案
将所有索引查找操作切换到当前行的字符串上,而非整个List:
private static void buildGUIFile() throws IOException { List<String> fileLines = Files.readAllLines(fileName); for (int i = 0; i < fileLines.size(); i++) { resNum = i + 1; String currentLine = fileLines.get(i).trim(); int beginIndex = currentLine.indexOf("<Price>"); int endIndex = currentLine.indexOf("</Price>"); try { // 先检查标签有效性,避免无效索引 if (beginIndex != -1 && endIndex != -1 && endIndex > beginIndex) { price = currentLine.substring(beginIndex + "<Price>".length(), endIndex); } else { price = "N/A"; System.out.println("Line " + resNum + ": 未找到有效的Price标签"); } } catch (StringIndexOutOfBoundsException e) { System.out.println("endIndex: " + endIndex); e.printStackTrace(); } } }
额外建议
字符串截取解析XML的方式非常脆弱,一旦XML格式出现微小变化(比如标签间换行、标签内加空格)就会失效。推荐使用标准XML解析库,比如轻量易用的jsoup:
import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.parser.Parser; // ... String currentLine = fileLines.get(i).trim(); // 用XML解析器解析单行内容 Document doc = Jsoup.parse(currentLine, "", Parser.xmlParser()); // 直接获取Price标签的文本内容 price = doc.selectFirst("Price").text();
内容的提问来源于stack exchange,提问作者joseph michaels
相关产品推荐
相关产品推荐

