ArrayList的IndexOutOfBounds(使用多个数字测试)

时间:2013-08-23 13:26:48

标签: java arraylist

因此,每当我尝试在这个特定文本中使用此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);
}
}

感谢未来的帮助,我似乎无法弄清楚问题。如果你想要一些东西放在一个文本文件中,这里有一些东西:

5 个答案:

答案 0 :(得分: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> lines中的getStart()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:Index:19,Size:0

答案 1 :(得分: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。

答案 2 :(得分:0)

我认为错误可以缩小到这个:

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

此处,end是参数。你从哪里获得价值?您应该检查边界,以便endlines.size()之前使用lines.size()不会超过int max = end > lines.size() ? lines.size() : end; int max = start > lines.size() ? lines.size() : start; 。像这样:

15

如果实际大小为end20上升到is.reset(); tempSB = new BufferedReader(new InputStreamReader(is)); ,则当迭代继续到比列表边界更远的索引时,会弹出异常。相同的逻辑适用于start,但反过来。


修改

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

{{1}}

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

答案 3 :(得分:0)

根本原因是您正在重复使用storyFile输入流。您的方法getIntroText()将完全读取storyFile输入流中的所有数据,直到结束,并且流将为空。之后,当您拨打getStart()时,由于正在使用相同的流,因此不再需要从流中读取数据,lines列表将为空!!简单修复,定义另一个流并将其用于getStart() ..(有更有效的方法来执行此操作,但您提到您将使用它...)

答案 4 :(得分:0)

在堆栈中查看大小为0的信息。

我认为如果你尝试从同一个文件中读取两次,那么第二次将你的流清空。