import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
class Untitled {
public static void main(String[] args) throws IOException {
String content = new String(Files.readAllBytes(Paths.get("YUGECORPUS.txt")));
content = content.replace("\n", " ").replace("\r", " ");
String search = "George Bush is";
System.out.print(content.substring(content.indexOf(search), content.substring(content.indexOf(search)).indexOf(".")));
}
}
编译代码时收到的错误如下:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -3073945
at java.lang.String.substring(String.java:1967)
at Untitled.main(main.java:14)
。
如何修复此错误,为什么会发生错误?上面代码段中以下代码的用途:
content.substring(content.indexOf(search), content.substring(content.indexOf(search)).indexOf("."))
从content
第一次出现的开头到第一次出现的句号search
,打印字符串.
中的文字。
答案 0 :(得分:0)
您尝试查找.
的索引时出错:
content.substring(content.indexOf(search)).indexOf(".")
将为您提供子字符串内的索引,而不是content
内的索引。要解决此问题,请将search
的起始索引添加到其中。
例如,如果content
为:123George Bush is45.
,那么我们就会:
content.indexOf(search) -> 3
content.substring(content.indexOf(search)) -> "George Bush is45."
因此:
content.substring(content.indexOf(search)).indexOf(".") -> 16
这是不正确的,正确的索引是16 + 3 = 19:
content.substring(3, 16) -> "George Bush i" // wrong
content.substring(3, 19) -> "George Bush is45" // correct
如果content
未包含您的search
字符串且连续.
,则您的代码也可能无法正常运行并生成例外。
为了使代码更具错误证明,如果content
包含您期望的内容,您可以添加检查,如此(请注意endIndex += startIndex
处的修复):
int startIndex = content.indexOf(search);
if(startIndex > -1) {
int endIndex = content.substring(startIndex).indexOf(".");
if(endIndex > -1) {
endIndex += startIndex;
String foundString = content.substring(startIndex, endIndex);
System.out.print(foundString);
}
}
明确地进行检查而不是将所有内容放在一行中也会使代码更容易调试并发现错误。
@Andreas指出编辑,说明
int endIndex = content.substring(startIndex).indexOf(".");
endIndex += startIndex;
可以简化
int endIndex = content.indexOf('.', startIndex);
这是更新的代码:
int startIndex = content.indexOf(search);
if(startIndex > -1) {
int endIndex = content.indexOf('.', startIndex);
if(endIndex > -1) {
String foundString = content.substring(startIndex, endIndex);
System.out.print(foundString);
}
}
答案 1 :(得分:0)
它接收你的子串并找到它,然后再次读取文件并找到第一个期间。所以,什么时候
此。一些东西。乔治布什是等等等等。
它将你的第一个参数作为一个比第二个更大的数字,因为它在&#34之后找到第一个时期;这个"。
如果你想继续这样做,你必须在找到&#34之后截断字符串;乔治布什是"把它放在字符串的开头。
答案 2 :(得分:0)
为了帮助我们,您应该提供MCVE。这可以通过替换方法中的第一行来轻松完成,例如
String content = "In a galaxy far, far away, George Bush is happy. That is good.";
这样,我们实际上可以重现您的问题。
所以,完成后,让我们分解你的代码,看看出了什么问题:
String content = "In a galaxy far, far away, George Bush is happy. That is good.";
content = content.replace("\n", " ").replace("\r", " ");
String search = "George Bush is";
int searchIdx = content.indexOf(search);
String substring = content.substring(searchIdx);
int periodIdx = substring.indexOf(".");
System.out.println("searchIdx = " + searchIdx);
System.out.println("substring = " + substring);
System.out.println("periodIdx = " + periodIdx);
System.out.print("content.substring(" + searchIdx + ", " + periodIdx + ") = ");
System.out.flush();
System.out.println(content.substring(searchIdx, periodIdx));
输出
searchIdx = 27
substring = George Bush is happy. That is good.
periodIdx = 20
content.substring(27, 20) = Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -7
at java.lang.String.substring(String.java:1967)
at Test.main(Test.java:18)
您可以在此处看到问题是periodIdx
为20,即小于searchIdx
值27,导致substring(27, 20)
失败。
这是因为periodIdx
是substring
的索引,而不是content
的索引。
解决此问题的一种方法是简单地将searchIdx
添加到periodIdx
,例如
int periodIdx = substring.indexOf(".") + searchIdx;
输出
searchIdx = 27
substring = George Bush is happy. That is good.
periodIdx = 47
content.substring(27, 47) = George Bush is happy
修复它的另一种方法是改为对substring
变量进行子串,因为这是索引的用途:
int periodIdx = substring.indexOf(".");
System.out.print("substring.substring(0, " + periodIdx + ") = ");
System.out.println(substring.substring(0, periodIdx));
输出
substring.substring(0, 20) = George Bush is happy
以前的两种解决方案都能为您提供所需的结果。但它们不是理想的解决方案,因为content.substring(searchIdx)
在创建子字符串时会使用副本。
更好的解决方案是在第一次查找返回的点执行第二次索引启动:
int searchIdx = content.indexOf(search);
int periodIdx = content.indexOf('.', searchIdx);
System.out.print("content.substring(" + searchIdx + ", " + periodIdx + ") = ");
System.out.println(content.substring(searchIdx, periodIdx));
输出
content.substring(27, 47) = George Bush is happy
另请注意,indexOf()
的搜索值已从"."
更改为'.'
,因为搜索单个字符比搜索字符串更快,甚至单字符串。
这是更好的代码。
您的main()
方法应为:
public static void main(String[] args) throws IOException {
String content = new String(Files.readAllBytes(Paths.get("YUGECORPUS.txt")));
content = content.replace("\n", " ").replace("\r", " ");
String search = "George Bush is";
int searchIdx = content.indexOf(search);
System.out.print(content.substring(searchIdx, content.indexOf('.', searchIdx)));
}
请注意,searchIdx
是单独完成的,所以只需要完成一次,不像您的代码必须搜索超过300万(!)字符两次强>
它还使代码更具可读性。