1

因此,每当我尝试在此特定文本中使用此 ArrayList 时,都会遇到此错误。所以这是问题代码:

public static String lines(int start, int end, InputStream is) {
    try {
        BufferedReader fileBR = new BufferedReader(new InputStreamReader(is));
        List<String> lines = new ArrayList<String>();
        String strLine;
        StringBuilder tempSB = new StringBuilder();

        while ((strLine = fileBR.readLine()) != null) {
            lines.add(strLine);
        }

        for (int i = start - 1; i < end; i++) {
            tempSB.append(lines.get(i));
            tempSB.append("\n");
        }
        line = tempSB.toString();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return line;
}

我不确定该代码的效率如何,但在我的程序中的一些基本功能关闭后,我将通过并努力提高效率。问题是当我使用它时:

    // Edit lines according to where the headerFile starts
public static String getHeaderArt() {
    return lines(1, 21, headerFile);
}

// Change to get the introduction text from a file
public static String getIntroText() {
    return lines(2, 17, storyFile);
}

public static String getStart() {
    return lines(20, 27, storyFile);
}

出于某种原因,前两个代码有效,而第三个代码无效。我的故事情节文件有 28 行,所以我不确定它为什么不起作用。

堆栈跟踪:

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 19, Size: 0
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at com.hathorsrpg.DefaultText.lines(DefaultText.java:42)
at com.hathorsrpg.DefaultText.getStart(DefaultText.java:86)
at com.hathorsrpg.Main.intro(Main.java:23)
at com.hathorsrpg.Main.main(Main.java:87)

这是一个 SSCCE,没有文本文件:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class SSCCE {
public static InputStream storyFile = SSCCE.class.getResourceAsStream("/resources/storytext.txt");
public static InputStream headerFile = SSCCE.class.getResourceAsStream("/resources/castle.txt");

public static String line;

public static String lines(int start, int end, InputStream is) {
    try {
        BufferedReader fileBR = new BufferedReader(new InputStreamReader(is));
        List<String> lines = new ArrayList<String>();
        String strLine;
        StringBuilder tempSB = new StringBuilder();

        while ((strLine = fileBR.readLine()) != null) {
            lines.add(strLine);
        }

        for (int i = start - 1; i < end; i++) {
            tempSB.append(lines.get(i));
            tempSB.append("\n");
        }
        line = tempSB.toString();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return line;
}

// Edit lines according to where the headerFile starts
public static String getHeaderArt() {
    return lines(1, 21, headerFile);
}

// Change to get the introduction text from a file
public static String getIntroText() {
    return lines(2, 17, storyFile);
}

public static String getStart() {
    return lines(20, 27, storyFile);
}
}

感谢您未来的帮助,我似乎无法找出问题所在。如果您想将某些内容放入文本文件中,请执行以下操作:

4

5 回答 5

2

问题是你试图重用

public static InputStream storyFile

在通话getIntroText()getStart(). 虽然,传递的startend参数是不同的,但请注意您是如何从您的BufferedReader

while ((strLine = fileBR.readLine()) != null) { // read completely
    lines.add(strLine);
}

这意味着InputStream已经用尽并且无法再使用,getStart()因为这个时间fileBR.readLine()会返回NULL并且

while ((strLine = fileBR.readLine()) != null) {
    lines.add(strLine); // never gets executed
}

因此,List<String> linesingetStart()仍然为空,size() = 0但您的代码仍然继续并调用

for (int i = start - 1; i < end; i++) {
    tempSB.append(lines.get(i)); // index = 20 - 1 = 19
    tempSB.append("\n");
}

因此你得到

java.lang.IndexOutOfBoundsException:索引:19,大小:0

于 2013-08-23T13:43:52.757 回答
1

你的方法:

public static String getStart() {
    return lines(20, 27, storyFile);
}

正在尝试获取指定文件的第 20 到 27 行。但这是基于您的文件确实有至少 27 行的假设,这可能是也可能不是。

例如,如果您的文件只有 15 行,则尝试获取第 20 行将导致 IndexOutOfBoundsException。

这个问题的解决方案是这样的:

public static String lines(int start, int end, InputStream is) {
    try {
        BufferedReader fileBR = new BufferedReader(new InputStreamReader(is));
        List<String> lines = new ArrayList<String>();
        String strLine;
        StringBuilder tempSB = new StringBuilder();

        while ((strLine = fileBR.readLine()) != null) {
            lines.add(strLine);
        }

        int start = start <= lines.size - 1 ? start : lines.size - 1;
        int end = end <= lines.size - 1 ? end : lines.size - 1;

        for (int i = start; i < end; i++) {
            tempSB.append(lines.get(i));
            tempSB.append("\n");
        }
        line = tempSB.toString();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return line;
}

这样,如果您指定的开始或结束大于行数的上限,它将不会返回任何内容。如果只指定大于上限的结束索引,它将从开始索引返回到文件末尾,而不会导致 IndexOutOfBoundsException。

于 2013-08-23T13:42:50.193 回答
0

我认为错误可以缩小到:

for (int i = start - 1; i < end; i++) {
    tempSB.append(lines.get(i));
    tempSB.append("\n");
}

这里,end是一个参数。你从哪里获得价值?在这种情况下,您应该检查边界,以便end最终不会超过lines.size(),使用lines.size()。像这样的东西:

int max = end > lines.size() ? lines.size() : end;
int max = start > lines.size() ? lines.size() : start;

如果实际大小是15并且end上升到20,则当迭代继续到比列表边界更远的索引时会弹出异常。同样的逻辑适用于开始,但反过来。


编辑

此外,您的文件读取存在问题。当你第二次尝试阅读它时,它会筋疲力尽。像这样重置您的阅读器,以便能够再次阅读:

is.reset();
tempSB = new BufferedReader(new InputStreamReader(is));

另一方面,更好的方法是读取一次,保留数据并在整个应用程序中使用它。

于 2013-08-23T13:31:03.377 回答
0

Look that in the stack there is information that size is 0.

I think that if you try to read twice from the same file, the second time you have your stream empty.

于 2013-08-23T13:49:36.570 回答
0

根本原因是您正在重用storyFile 输入流。您的方法getIntroText()将完全从 storyFile 输入流中读取所有数据,直到最后,流将为空。之后,当您调用时getStart(),由于正在使用相同的流,因此不再从流中读取数据并且lines列表将为空!简单修复,再定义一个流并将其用于getStart()..(有更有效的方法可以做到这一点,但您提到您将继续努力...)

于 2013-08-23T13:46:38.707 回答