【问题标题】:Scanner missing first line of .txt file扫描仪缺少 .txt 文件的第一行
【发布时间】:2016-04-29 05:35:07
【问题描述】:

我认为我在做一些非常愚蠢的事情,但我是 Java 新手,所以请耐心等待。我正在使用 FileReader 和 Scanner 来读取 .txt 文件的行。抓取每一行后,我提取一些信息,然后移动该行。这是我的简化方法的样子:

Reader fileReader = new FileReader("test.txt");
Scanner scanner = new Scanner(fileReader);

public static textList(Scanner scanner){
   while (scanner.hasNextLine()){
      scanner.nextLine();
      while(scanner.hasNext()){
         // Extract information from each line and do some stuff with it
         // using scanner.next();
      }
   }
}
// scanner is closed in the same method that creates it and the FileReader.

我的问题是,如果我将 scanner.nextLine() 留在原处,我将始终跳过 .txt 文件的第一行,但如果我将其移动到 while( scanner.hasNextLine()) 的末尾,我会得到一个“当扫描仪到达 .txt 文件的末尾时,不存在这样的行”异常。

任何帮助和指导将不胜感激!

谢谢

【问题讨论】:

  • 为什么不使用 - while (scanner.hasNextLine()){ String s = scanner.nextLine() ... Other code here
  • 是否可以从 s 中提取不同的标记?我澄清一下,每行有5个数据串,我需要把这些数据位分开
  • nextLine() 使用并返回一行文本。 next() 跳过空格,消耗并返回一个令牌。因此,您调用 nextLine() 所使用的任何文本都将被丢弃,因为您不使用返回值。
  • @flexcookie - 是的,您可以在空格上拆分输入行以获取令牌
  • 是的。 s = scanner.nextLine() 会将下一行的内容分配给s,因为nextLine() 返回一个字符串。

标签: java methods java.util.scanner


【解决方案1】:

读取每行 5 个标记的文本文件的最佳方法是不使用 Scanner

Scanner 很慢,而且通常不会按照你的想法行事。

请改用BufferedReader。并使用 try-with-resources 关闭它。

try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {
    for (String line; (line = reader.readLine()) != null; ) {
        String[] tokens = line.split("\\s+");
        // use tokens array here
    }
}

对于更高级的行解析,您可以使用带有捕获组的完整正则表达式,而不是 split()

Pattern p = Pattern.compile("(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)");
try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {
    for (String line; (line = reader.readLine()) != null; ) {
        Matcher m = p.matcher(line);
        if (! m.matches())
            throw new IllegalArgumentException("Bad data: " + line);
        String token1 = m.group(1);
        String token2 = m.group(2);
        String token3 = m.group(3);
        String token4 = m.group(4);
        String token5 = m.group(5);
        // use tokens here
    }
}

该代码与第一个示例相同,但强制每行必须恰好有 5 个标记。然后可以根据需要调整正则表达式,例如通过使用\\d+ 而不是\\S+ 来确保token3 是一个数字。

【讨论】:

  • 我也会实现这个方法。谢谢!
【解决方案2】:

解决此问题的一种简单方法是按照this answer 中的方式进行操作 - 这样您甚至可以很好地解决多个空格:

String data = scanner.nextLine();
String[] pieces = data.split("\\s+");
// Parse the pieces

因为 .next() 默认只返回空格后的内容,在这里使用它而不是 this 没有任何好处。

【讨论】:

  • 太好了,这就是我要找的。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-05
  • 1970-01-01
相关资源
最近更新 更多