【问题标题】:How to detect end of line with Scanner from text file如何使用扫描仪从文本文件中检测行尾
【发布时间】:2013-08-06 18:51:03
【问题描述】:

所以我正在读取一个由 4 行单空格分隔的数字组成的输入文本文件。文本文件只是:

5 
9 6
4 6 8
0 7 1 5

我想将这些数字输入到一个称为行的二维数组中。例如,rows[1][0] 应该是 9,即第二行的第一个数字。

我的问题是,当我将扫描仪用于in.next()in.nextInt() 时,它会忽略行尾并继续运行,因此rows[0][1] 最终成为9 而不是0。如果该插槽没有编号,我希望数组完成填充0's。因此,由于第一行只有1 数字,5,我希望数组rows[0][0]5,但rows[0][1]rows[0][3]0

我尝试对 NoSuchElementException 和 if in.hasNextLine() 使用 try/catch,但这些似乎都不起作用。

任何想法或帮助将不胜感激。

【问题讨论】:

  • 欢迎来到 Stackoverflow。你能发布你的代码吗?我们很乐意为您提供帮助

标签: java arrays file input line


【解决方案1】:

使用多个扫描仪。一个 Scanner 使用nextLine() 获取每一行,然后将获得的行提供给下一个 Scanner 分析每一行的令牌。使用完内部 Scanner(以及外部 Scanner)后,请务必 close()。

伪代码:

create fileScanner with file
while fileScanner has more lines
  get next line from fileScanner
  create new Scanner with next line, lineScanner
  while lineScanner has next, 
    get next token.
    do what you want with token.
  close of lineScanner
close fileScanner

【讨论】:

  • @JasonC:哎呀!!!不知道我在想什么。 close() 是正确的调用方法。谢谢!
【解决方案2】:

您可以使用 Scanner 读取单个令牌,也可以使用 Scanner 读取整行,但不能同时使用 Scanner。

您要做的是首先将该行读入一个字符串,然后在该字符串上使用扫描仪来解析该行,例如:

BufferedReader lineReader = new BufferedReader(...);
String line;

while ((line = lineReader.readLine()) != null) {
    Scanner scanner = new Scanner(line); 
    // use scanner here
}

您也可以使用 Scanner 而不是 BufferedReader 来读取行,但除非您有特定要求(例如,您试图将其放入已经使用 Scanner 的代码中),否则您如何使用并不重要阅读这些行。

希望对您有所帮助。

【讨论】:

    【解决方案3】:
    Scanner scanner = new Scanner(
                "5\n9 6\n4 6 8\n0 7 1 5");
    
    while (scanner.hasNextLine())
    {
        String currentline = scanner.nextLine();
    
        String[] items = currentline.split(" ");
        int[] intitems = new int[items.length];
    
        for (int i = 0; i < items.length; i++)
        {
            intitem[i] = Integer.parseInt(items[i]);
        }
    }
    

    【讨论】:

      【解决方案4】:

      您可能应该使用BufferedReadersplit。这样做的好处是您知道在第二维中制作数组有多大,因为split 方法将返回一个数组,您可以检查它的length

      public static void main(String[] args) throws Exception {
          final String s = "5\n"
                  + "9 6\n"
                  + "4 6 8\n"
                  + "0 7 1 5";
          final InputStream is = new ByteArrayInputStream(s.getBytes());
          final int[][] array = new int[4][];
          try (final BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
              String line;
              for (int i = 0; (line = br.readLine()) != null; ++i) {
                  final String[] tokens = line.split("\\s");
                  final int[] parsed = new int[tokens.length];
                  for (int j = 0; j < tokens.length; ++j) {
                      parsed[j] = Integer.parseInt(tokens[j]);
                  }
                  array[i] = parsed;
              }
          }
          System.out.println(Arrays.deepToString(array));
      }
      

      输出:

      [[5], [9, 6], [4, 6, 8], [0, 7, 1, 5]]
      

      由于数组不会扩展,因此在您不知道其大小的 while 循环中使用它们并不容易。使用split 可以让您简单地执行final int[] parsed = new int[tokens.length];,而在空白处使用Scanner 是您无法做到的。

      第一个维度的大小是硬编码的,但是如上所述,您的文件总是有 4 行。

      【讨论】:

      • 或者,您可以使用 ArrayList 或其他容器来消除必须提前知道令牌数量的要求。
      • @JasonC 当然,只是 OP 指定需要一个二维数组。我想也可以一直到List.toArray(),但这似乎有点浪费——在Lists 和数组之间来回复制数据。
      【解决方案5】:

      在每行的end,有'\n',并且在每行的first除了第一行),有'\r'。您可以通过它们控制您的文件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-23
        相关资源
        最近更新 更多