Java 扫描程序未遍历整个文件

Java scanner not going through entire file

提问人:Fizzmaister 提问时间:12/1/2011 更新时间:12/20/2022 访问量:29208

问:

我正在用 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的文件,该文件对路径进行编码。任何帮助将不胜感激。

谢谢。

java 文件-io java.util.scanner

评论

1赞 NPE 12/1/2011
你能把实际的数据文件上传到我们可以看的地方吗?
1赞 Hovercraft Full Of Eels 12/1/2011
是否有任何例外情况?有空的捕获块吗?
0赞 Fizzmaister 12/1/2011
我希望pastebin对每个人都有用。数据
0赞 Fizzmaister 12/1/2011
哦,没有例外。我没有使用 try catch,因为我很懒,我可以保证文件的位置,因为只有我在使用它,没有其他人。
0赞 Bryan 12/1/2011
如果你把一个println放在你的while循环中会发生什么?

答:

20赞 Hovercraft Full Of Eels 12/1/2011 #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());

并表明它认为文件已经结束。我正在逐步删除从数据到文件的行,以查看是哪一行导致了问题,但会把它留给你。

评论

1赞 Fizzmaister 12/1/2011
谢谢,它奏效了。我不知道扫描仪出了什么问题,但它可以读取所有内容。
3赞 Bryan 12/1/2011
所以我们永远不会知道。:/
0赞 Hovercraft Full Of Eels 12/1/2011
@Bryan:希望 Fizzmaister 能找到问题并报告。我会的,但我在办公室工作上落后了!:o
0赞 Fizzmaister 12/1/2011
这实际上有点尴尬,但我现在无法重现错误。我注释掉了我的旧方法并添加了这个方法(没问题),将数据复制粘贴到一个新文件中并尝试使用旧方法(没问题),切换回第一个文件和旧方法(仍然没有问题)。这似乎是一个千古之谜。
2赞 rfeak 12/1/2011
复制和粘贴文件内容可能更改了编码。您会惊讶于某些文本编辑器会自动执行的操作。
5赞 The Aa of Ron 6/22/2012 #2

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

我重新保存了我正在阅读的内容,它解决了问题。事实证明,记事本默认为 ANSI。.txtUTF-8

-3赞 B V S REDDY 8/3/2012 #3

你应该使用这个:

扫描程序扫描程序 = new Scanner(fileObj).useDelimiter(“\z”);
System.out.println(scanner.next());

评论

2赞 wvdz 4/21/2015
这甚至不能编译,如果你把它更正为编译,它并不能解决这个问题。
11赞 Learner123 4/23/2013 #4

我遇到了同样的问题,这就是我为解决它所做的:

  1. 将我正在读取的文件保存到 UTF-8 中
  2. 创建了新的扫描仪,如下所示,指定编码类型:
    Scanner scanner = new Scanner(new File("C:/IDSBRIEF/GuidData/"+sFileName),"UTF-8");  
    

评论

1赞 Mar 1/28/2014
这解决了我的问题。基本上,我的扫描仪采用一种编码,而Notepad++采用另一种编码。当我在两个地方指定相同的编码时,我的问题就解决了。
0赞 Cloud Walker 10/8/2021
我尝试打印出扫描仪每次读取的内容,在指定编码类型之前,我在输出中得到随机字符,而在指定“UTF-8”后,显示的输出是正常的。我认为这表明编码确实是问题所在。
0赞 evaldeslacasa 6/7/2014 #5

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

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

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

2赞 golimar 10/24/2018 #6

我的具体情况:

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

结论

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

溶液

  • 忘记扫描仪并使用

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

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

评论

1赞 Marcello Nuccio 10/26/2018
好吧,忘掉 Scanner,但不要忘记 Charset!如果不知道输入字符集,则无法可靠地将字节转换为字符串。我被这些错误烧了很多次。即使是行尾也可能随便被错误地解释。最糟糕的是,这些错误可能需要多年的日常使用才能出现。你已经被警告了。
0赞 golimar 10/26/2018
就我而言,它是扫描仪方法,需要多年的日常使用才能显示;)(这些文件应该是仅 ASCII 的,直到有人设法添加一些奇怪的字符并以与 Java 源文件编码不同的编码编写文件......
0赞 Marcello Nuccio 10/26/2018
我不明白的是:你为什么不指定字符集?平台的默认字符集是一个随机值,如果你不是小心总是正确设置它。如果要使用 ASCII 编码,那么为什么不使用 instead 代替?旁注:ASCII 是一种七位编码,也许ISO_8859_1是一个更好的选择。new String(bytes, StandardCharsets.US_ASCII)new String(bytes)
0赞 golimar 10/26/2018
我只想要 ascii 部分(它们是系统命令)并丢弃可能的非 ascii 部分(用户注释,有时以 ISO_8859_1 编码,有时以 UTF-8 或任何其他编码编码,具体取决于用户和他们用于创建、传输或复制粘贴文件的程序)。所以对我来说重要的是确保整个文件被读取
1赞 Bastien Gallienne 10/26/2022
我测试了新的文件(fil),“Cp1252”),它遍历了整个文件。谢谢,这已经解除了我的封锁。
0赞 user8373873 12/23/2018 #7

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

Scanner scanner = new Scanner(new File(filename),“UTF-8”);

1赞 anakin59490 2/6/2019 #8

我在 csv 文件上遇到了同样的问题:它可以在 Windows 上运行,但在 Linux 上不起作用

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

0赞 Sultan 8/19/2021 #9

这是我倾向于做的:

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();
0赞 Bastien Gallienne 10/26/2022 #10

我接管了一个 4MB 奇怪的 CSV 文件,该文件在多个地方抛出读取错误:

1.在 Cp1252 中打开文件

2.立即将其以UTF-8保存在第二个文件中

  1. 现在在第二个文件上调用您扫描仪。