【问题标题】:Java scanner not going through entire fileJava 扫描器没有遍历整个文件
【发布时间】:2012-01-09 23:15:52
【问题描述】:

我正在用 Java 编写一个程序,我需要做的一件事是为最短路径问题创建一组每个有效位置。这些位置在 .txt 文件中定义,该文件遵循严格的模式(每行一个条目,没有额外的空格),非常适合使用 .nextLine 获取数据。我的问题是文件中的 241 行(共 432 行)扫描仪在通过条目的 3/4 处停止工作并且无法识别任何新行。

我的代码:

    //initialize state space
private static Set<String> posible(String posLoc) throws FileNotFoundException {
    Scanner s = new Scanner(new File(posLoc));
    Set<String> result = new TreeSet<String>();
    String availalbe;
    while(s.hasNextLine()) {
        availalbe = s.nextLine();
        result.add(availalbe);
    }
    s.close();
    return result;
}

数据

Shenlong Gundam
Altron Gundam
Tallgee[scanner stops reading here]se
Tallgeese II
Leo (Ground)
Leo (Space)

当然,“扫描仪在此处停止读取”不在数据中,我只是在标记扫描仪停止读取文件的位置。这是文件中的 3068 个字节,但这不会影响任何内容,因为在同一个程序中,使用几乎相同的代码,我正在读取一个 261 行、14KB 的 .txt 文件,该文件对路径进行编码。任何帮助将不胜感激。

谢谢。

【问题讨论】:

  • 你能把实际的数据文件上传到我们可以查看的地方吗?
  • 有没有抛出异常?是否有空的 catch 块?
  • 我希望 pastebin 对每个人都有效。 data
  • 哦,没有抛出异常。我没有使用try catch,因为我很懒,我可以保证文件的位置,因为只有我在使用它,没有其他人使用。
  • 如果在 while 循环中放置 println 会发生什么?

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


【解决方案1】:

扫描仪读取您的文件时出现问题,但我不确定是什么问题。它错误地认为它已经到达文件末尾,而实际上它没有到达,可能是由于一些时髦的字符串编码。尝试使用包装 FileReader 对象的 BufferedReader 对象。

例如,

   private static Set<String> posible2(String posLoc) {
      Set<String> result = new TreeSet<String>();
      BufferedReader br = null;
      try {
         br = new BufferedReader(new FileReader(new File(posLoc)));
         String availalbe;
         while((availalbe = br.readLine()) != null) {
             result.add(availalbe);            
         }
      } catch (FileNotFoundException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      } finally {
         if (br != null) {
            try {
               br.close();
            } catch (IOException e) {
               e.printStackTrace();
            }
         }
      }
      return result;
  }

编辑
我尝试将您的问题减少到最低限度,这足以引发问题:

   public static void main(String[] args) {
      try {
         Scanner scanner = new Scanner(new File(FILE_POS));
         int count = 0;
         while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            System.out.printf("%3d: %s %n", count, line );
            count++;
         }

我用 printf 检查了 Scanner 对象:

System.out.printf("Str: %-35s size%5d; Has next line? %b%n", availalbe, result.size(), s.hasNextLine());

并表明它认为文件已经结束。我正在逐步从数据中删除行到文件中,以查看导致问题的行,但将留给您。

【讨论】:

  • 谢谢,它成功了。我不知道扫描仪出了什么问题,但它可以读取所有内容。
  • 所以我们永远不会知道。 ://
  • @Bryan:希望 Fizzmaister 能找到问题并报告。我会的,但我在办公室工作上落后了! :o
  • 这其实有些尴尬,但是我现在无法重现错误。我注释掉了我的旧方法并添加了这个方法(没问题),将数据复制粘贴到一个新文件中并尝试使用旧方法(没问题),切换回第一个文件和旧方法(仍然没问题)。这似乎将成为千古之谜。
  • 复制和粘贴文件内容可能改变了编码。您会惊讶于某些文本编辑器会自动执行的操作。
【解决方案2】:

我遇到了同样的问题,这就是我要解决的问题:

1.Saved the file I was reading from into UTF-8
2.Created new Scanner like below, specifying the encoding type:


   Scanner scanner = new Scanner(new File("C:/IDSBRIEF/GuidData/"+sFileName),"UTF-8");   

【讨论】:

  • 这解决了我的问题。基本上,我的扫描仪采用一种编码,而 Notepad++ 采用另一种编码。当我在两个地方指定相同的编码时,我的问题就解决了。
  • 我试图打印出扫描仪每次读取的内容,在我指定编码类型之前,我在输出中得到了随机字符,而在我指定“UTF-8”之后,显示的输出是正常的.我认为这表明编码确实是问题。
【解决方案3】:

我遇到了同样的问题。扫描仪不会读到文件的末尾,实际上是在一个单词的中间停止。我认为这是扫描仪设置了一些限制的问题,但我注意到了 rfeak 关于字符编码的评论。

我将正在阅读的.txt 重新保存到UTF-8,它解决了问题。原来记事本默认是ANSI的。

【讨论】:

    【解决方案4】:

    我的情况:

    • 在我的主程序 (A) 中,它总是从 41021 字节的文件中读取 16384 字节。它停止的字符位于带有正常可打印文本的行的中间
    • 如果我创建一个单独的小程序 (B),只有 Scanner 和 print 行,它会读取整个文件
    • 在 (A) 中指定“UTF-8”仍为 16384
    • 在 (A) 中指定“ASCII”仍为 16384
    • 在 (A) 中指定“Cp1252”会读取整个文件
    • 我的输入 txt 文件是由用户发送的,我不能确定他们是否会以任何特定的编码编写它们

    结论

    • 扫描器似乎逐块读取文件并将正确读取的数据写入返回字符串,但是当它发现一个编码与预期不同的块时,它静默退出(哎哟) 并返回部分字符串
    • 我试图读取的 txt 文件是 Cp1252,我的 (A) 源文件是 UTF-8,我的 (B) 源文件是 Cp1252,所以这就是为什么 (B) 在没有指定编码的情况下工作

    解决方案

    • 忘记扫描仪并使用

    String fullFileContents = new String(Files.readAllBytes(myFile.toPath()));

    当然,由于您不知道编码,因此无法像这样可靠地读取非 ascii 字符,但是肯定会读取 ascii 字符。如果您只需要文件中的 ascii 字符并且可以丢弃非 ascii 部分,请使用它。

    【讨论】:

    • 好的,忘记扫描仪,但不要忘记字符集!在不知道输入字符集的情况下,您无法可靠地将字节转换为字符串。我被这些错误烧伤了很多次。即使是行尾也可以随便解释为错误的方式。最糟糕的是,这些错误可能需要多年的日常使用才能出现。您已收到警告。
    • 在我的情况下,扫描仪方法需要多年的日常使用才能出现;)(文件应该是 ascii-only,直到有人设法添加一些奇怪的字符并将文件写入与 Java 源文件编码不同的编码...)
    • 我不明白的是:你为什么不指定字符集?平台的默认字符集是一个随机值,如果您真的不小心始终正确设置它。如果要使用 ASCII 编码,那为什么不用new String(bytes, StandardCharsets.US_ASCII) 而不是new String(bytes)?旁注:ASCII 是七位编码,也许 ISO_8859_1 更好。
    • 我只想要 ascii 部分(它们是系统命令)并丢弃可能的非 ascii 部分(用户 cmets,有时用 ISO_8859_1 编码,有时用 UTF-8 甚至任何其他编码,取决于用户和他们用来创建、传输或复制粘贴文件的程序)。所以对我来说重要的是确保读取整个文件
    • 但是你为什么不指定字符集呢?
    【解决方案5】:

    我有一个 txt 文件,其中 Scanner 在第 862 行停止读取,这是一个奇怪的问题。我所做的是创建一个不同的文件(尝试复制问题)。我先添加了少于 862 行,然后添加了超过 862 的行,它运行良好。

    所以我认为问题出在我之前的文件中,在第 862 行,有一些错误,比如某些字符或符号可能会误导 Scanner 提前完成读取。

    总结:根据这一经验,我建议找出扫描仪停止读取的确切行,以找到解决此类问题的方法。

    【讨论】:

      【解决方案6】:

      我的 Linux 服务器上也有类似的问题,最后下面的代码对我有用。

      Scanner 扫描仪 = new Scanner(new File(filename),"UTF-8");

      【讨论】:

        【解决方案7】:

        我在使用 csv 文件时遇到了同样的问题:它在 Windows 上工作,但在 Linux 上却不工作

        使用 nodepad++ 打开文件并更改编码,选择:在 UTF8 中编码(带 BOM)。 它解决了我的问题

        【讨论】:

          【解决方案8】:

          这是我倾向于做的事情:

          StringBuilder fileContents = new StringBuilder();
          File file = new File(Location);
          try (BufferedReader reader = new BufferedReader(new FileReader(file, StandardCharsets.UTF_8))) {
              String line;
              while ((line = reader.readLine()) != null) {
                  fileContents.append(line);
                  fileContents.append(System.lineSeparator());
              }
          }
          
          String outcome = fileContents.toString();
          

          【讨论】:

            【解决方案9】:

            你应该使用这个:

            Scanner 扫描器 = new Scanner(fileObj).useDelimiter("\z");
            System.out.println(scanner.next());

            【讨论】:

            • 这甚至不能编译,如果你更正它以编译,它并没有接近解决这个问题。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-04-01
            • 1970-01-01
            • 1970-01-01
            • 2015-02-16
            • 2011-04-20
            • 2016-09-21
            相关资源
            最近更新 更多