【问题标题】:Java - Scanner not scanning after a certain number of linesJava - 扫描仪在一定数量的行后不扫描
【发布时间】:2011-11-13 11:47:18
【问题描述】:

我正在用 Java 做一些相对简单的 I/O。我有一个使用扫描仪读取的 .txt 文件和一个使用 BufferedWriter 写入的 .txt 文件。然后另一个 Scanner 读取该文件,另一个 BufferedWriter 然后创建另一个 .txt 文件。我提供了下面的代码以防万一,但我不知道它是否会有太大帮助,因为我认为代码不是这里的问题。代码编译没有任何错误,但它没有按照我的预期进行。出于某种原因,charReader 将只读取其文件的大约一半,然后 hasNext() 将返回 false,即使尚未到达文件末尾。这些不是大的文本文件——statsReader 的文件是 34 KB,而 charReader 的文件是 29 KB,这更奇怪,因为 statsReader 可以很好地读取整个文件,而且更大!另外,我确实在 try/catch 中包含了该代码,只是没有包含它。

根据我在网上查到的,这可能会发生在非常大的文件中,但这些文件非常小,所以我很迷茫。

我的操作系统是 Windows 7 64 位。

        Scanner statsReader = new Scanner(statsFile);
        BufferedWriter statsWriter = new BufferedWriter(new FileWriter(outputFile));

        while (statsReader.hasNext()) {
            statsWriter.write(statsReader.next());
            name = statsReader.nextLine();
            temp = statsReader.nextLine();
            if (temp.contains("form")) {
                name += " " + temp;
                temp = statsReader.next();
            }
            statsWriter.write(name);
            statsWriter.newLine();
            statsWriter.write(temp);
            if (! (temp = statsReader.next()).equals("-"))
                statsWriter.write("/" + temp);
            statsWriter.write("\t");
            statsWriter.write(statsReader.nextInt() + "\t");
            statsWriter.write(statsReader.nextInt() + "\t");
            statsWriter.write(statsReader.nextInt() + "\t");
            statsWriter.write(statsReader.nextInt() + "\t");
            statsWriter.write(statsReader.nextInt() + "\t");
            statsWriter.write(statsReader.nextInt() + "");
            statsWriter.newLine();
            statsReader.nextInt();
        }

        Scanner charReader = new Scanner(charFile);
        BufferedWriter codeWriter = new BufferedWriter(new FileWriter(codeFile));   

        while (charReader.hasNext()) {
            color = charReader.next();
            name = charReader.nextLine();
            name = name.replaceAll("\t", "");
            typing = pokeReader.next();
            place = charReader.nextInt();
            area = charReader.nextInt();
            def = charReader.nextInt();
            shape = charReader.nextInt();
            size = charReader.nextInt();
            spe = charReader.nextInt();

            index = typing.indexOf('/');
            if (index == -1) {
                typeOne = determineType(typing);
                typeTwo = '0';
            }
            else {
                typeOne = determineType(typing.substring(0, index));
                typeTwo = determineType(typing.substring(index+1, typing.length()));
            }
        }

SSCCE:

public class Tester {
public static void main(String[] args) {
    File statsFile = new File("stats.txt");
    File testFile = new File("test.txt");
    try {
        Scanner statsReader = new Scanner(statsFile);
        BufferedWriter statsWriter = new BufferedWriter(new FileWriter(testFile));
        while (statsReader.hasNext()) {
            statsWriter.write(statsReader.nextLine());
            statsWriter.newLine();
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

}

【问题讨论】:

  • 它总是在同一个地方拉屎吗?您是否尝试简化文本文件以隔离那里的问题?您是否简化了 Java 代码以隔离重现问题的最小可编译子集?你使用调试器还是穷人的调试器(System.out.println 语句)?
  • 是的;每次都在同一个地方。是的,我做了一个循环,在 statsReader.hasNext() 时只执行 codeWriter.write(charReader.nextLine()),它也做了同样的事情。我正在使用 Eclipse,并使用这两种调试方法。
  • 好的,很好。现在,如果可以,我建议您创建一个非常小的可编译和可运行的自包含程序(也称为SSCCE 以及一个小的可用数据文件,并将两者都发布在这里,以便我们可以重现您的问题并尝试修改代码以找到解决方案。
  • 好的。我制作了一个单独的程序,我所做的只是获取原始的 statsFile,在 hasNext() 为真时从其中读取扫描仪,并让 BufferedWriter 在每次迭代中写入 nextLine()。奇怪的是它仍然没有得到整个文件。这次它只得到了大约 3/4s 的文件。
  • @RC,Pastebin 没有与 SO 相同的保证后代。我认为代码属于这里(复制起来很简单)。

标签: java file-io java.util.scanner bufferedreader


【解决方案1】:

这是一个经典问题:在读取文件之前,您需要flushclose 输出流(在本例中为statsWriter)。

被缓冲后,它实际上不会通过调用write 来写入文件。调用flush 会强制它完成所有挂起的写操作。

这是OutputStream.flush() 的 javadoc:

刷新此输出流并强制写出任何缓冲的输出字节。 flush 的一般约定是调用它表示,如果先前写入的任何字节已被输出流的实现缓冲,则应立即将这些字节写入其预期目的地。

【讨论】:

  • 即使是经验丰富的开发人员也经常这样做。只有当我们的文件出现在我们身上时,这是我们首先要看的事情之一,因为它是多么容易(和愚蠢)的错误。
  • 谢谢,但我不确定我是否理解。我在读/写任何东西之前刷新了我的 BufferedWriters,但我得到了相同的结果。如果我在读/写之前关闭它们,我会收到编译错误,因为它们已经关闭。你是说我需要使用 OutputStream 而不是 BufferedWriter?此外,当 hasNext() 检查不应该返回 false 时,程序会停止,所以我认为这是 Scanner 的问题。
  • 没关系,我明白了。我只是将 statsWriter.close() 的位置更改为在声明第二组 Scanner/BufferedWriter 之前。谢谢!
【解决方案2】:

使用statsWriter 编写文件后,您需要调用:

statsWriter.flush();
statsWriter.close();

或者简单地说:

statsWriter.close();  // this will call flush();

这是因为您使用的是 Buffered Writer,它不会在您调用 write 函数时将所有内容写入文件,而是以缓冲块的形式写入。当您调用flush()close() 时,它会将缓冲区中的所有内容清空到文件中,并关闭流。

您需要为您的第二位作家做同样的事情。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多