【问题标题】:Java Exception in thread “main” java.util.NoSuchElementException - Using scanner to read files线程“main”中的 Java 异常 java.util.NoSuchElementException - 使用扫描仪读取文件
【发布时间】:2014-06-19 02:06:02
【问题描述】:

我已经搜索了有关该主题的各种主题,但找不到处于相同情况的任何人或到目前为止我可以使用的任何解决方案。

我只想读取格式为 txt 的文件: 双0 双0 Int0 双 1 双 1 整数 1 .. 双倍双倍国际

这是我的代码:

public void readDatabase(String s) throws FileNotFoundException{    
    try {               
            BufferedReader br = new BufferedReader(new FileReader(s));
            String line = br.readLine();
            Scanner trainFile = null;
            while (line != null) {      
                line.trim();
                trainFile = new Scanner(line);
                double x = trainFile.nextDouble();
                double y = trainFile.nextDouble();
                int type = trainFile.nextInt();
                this.database.add(new Point(x,y,type));
                line = br.readLine();
            }   
            trainFile.close();
            br.close();
    }
    catch (IOException ioe) {
        ioe.printStackTrace();
    }
}

有趣的是,这个函数工作了一段时间,但是当我用更多数据填充 txt 文件时,它停止工作。我还检查了文件是否存在最终错误,但一切都很好。根据我的堆栈跟踪,该错误出现在第一个 NextDouble() 调用中。有人有想法吗?

更新:

这是正在运行的文件类型:

0,6580097206539348  0,36101701387184226 2
0,9529350156283241  0,7383387609711926  2
0,6580097206539348  0,36101701387184226 2
0,9529350156283241  0,7383387609711926  2
0,6580097206539348  0,36101701387184226 2
0,48639272096486486 0,4378985495387871  1

但如果我像这样添加一些额外的行,它就会停止工作:

0,6580097206539348  0,36101701387184226 2
0,9529350156283241  0,7383387609711926  2
0,6580097206539348  0,36101701387184226 2
0,9529350156283241  0,7383387609711926  2
0,6580097206539348  0,36101701387184226 2
0,48639272096486486 0,4378985495387871  1
0,8632344357711337  0,5253407956535258  1
0,7351912765040557  0,8295830810436339  1
0,6369155743204543  0,2757349130759706  1
0,46512947234632146 0,4388586141249502  1
0,8677892876429869  0,599451235810409   1
0,8827084731154641  0,55652107505414    1

【问题讨论】:

  • 为了帮助别人回答,你也需要分享你的文件。
  • 输入文件的结构很可能有问题。检查不正确的换行符或共享文件内容
  • 另一个额外的信息:我有以下文件:0,6580097206539348 0,36101701387184226 2 0,9529350156283241 0,7383387609711926 2 0,6580097206539348 0,36101701387184226 2 0,9529350156283241 0,7383387609711926 2 0,6580097206539348 0 ,36101701387184226 2 0,48639272096486486 0,4378985495387871 1 并且我的代码有效,当我在 eof 0,8632344357711337 0,5253407956535258 1 添加以下新行时,它会引发错误。
  • 0,6580097206539348 的格式不正确,无法解析为双精度。用点替换逗号就可以了。
  • 我的意思是我的代码对某些输入有效,而对另一些输入则不能。阅读我上面的评论和解释

标签: java


【解决方案1】:

根据 JavaDoc nextDouble() 扫描下一个 token 输入为双精度。此方法将抛出InputMismatchException if 下一个标记无法转换为有效的双精度值。

所以这里Scanner 无法在您的行0,6580097206539348 0,36101701387184226 2 中找到Double。有一种解决方案是在循环期间将, 替换为.(仅当您的每一行均不包含逗号时才用于此目的)

举例

  String yourLine="0,6580097206539348  0,36101701387184226 2"
  Scanner trainFile = new Scanner(line.replace(',', '.'));
               double x = trainFile.nextDouble();
               double y = trainFile.nextDouble();
               int type = trainFile.nextInt();

此外,对于从Exception 生存,您可以使用hasNextDoubel(),hasNextInt() 方法让Scanner 检查数据中是否存在double/int,它返回true/false。您可以在#Scanner 阅读更多相关信息

【讨论】:

    【解决方案2】:

    下一个输入应该总是是双精度的,对吧?所以不是while(line != null)(当你有一个空行时会返回true)检查while(scanner.hasNextDouble())

    public void readDatabase(String s) throws FileNotFoundException{    
        try {               
            final BufferedReader br = new BufferedReader(new FileReader(s));
            final Scanner trainFile = new Scanner(br);
            while (trainFile.hasNextDouble()) {      
                double x = trainFile.nextDouble();
                double y = trainFile.nextDouble();
                int type = trainFile.nextInt();
                this.database.add(new Point(x,y,type));
            }   
            trainFile.close();
            br.close();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
    

    您仍然需要将逗号更改为小数点。否则上述方法将不起作用。

    如果您的文件有逗号并且您需要将其解释为小数点,那么您可以尝试以下操作:

    public void readDatabase(String s) throws FileNotFoundException{    
        try {               
            final BufferedReader br = new BufferedReader(new FileReader(s));
            String line = br.readLine();
            while(line != null) {
                line = line.replace(',', '.');
                final Scanner lineScanner = new Scanner(line);
                if(!scanner.hasNextDouble())
                    break;// quit loop
                // else continue loop
                double x = lineScanner.nextDouble();
                double y = lineScanner.nextDouble();
                int type = lineScanner.nextInt();
                this.database.add(new Point(x,y,type));
                line = br.readLine();
            }   
            br.close();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
    

    【讨论】:

    • 您发布的第一个代码是唯一对我有用的解决方案。谢谢!
    • 我不明白您的 JRE 设置是如何将逗号解释为小数点的。
    【解决方案3】:

    在 java 中,您无法解析双精度数,因为逗号代替了小数点。编辑您的文件以使用句点而不是逗号。

    我通过运行以下函数测试了代码:

    public static void readDatabase(String s) throws FileNotFoundException {
    
        File file = new File(s);
        Scanner scanner = new Scanner(file);
    
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine();
            String[] values = line.split(" ");
            double x = Double.parseDouble(values[0]);
            double y = Double.parseDouble(values[1]);
            int type = Integer.parseInt(values[2]);
            System.out.println(x + " : " + y + " : " + type);
        }
        scanner.close();
    }
    

    关于文件:

    1.1 1.2 1 
    2.1 2.2 2 
    3.1 3.2 3
    

    得到了结果:

    1.1 : 1.2 : 1
    2.1 : 2.2 : 2
    3.1 : 3.2 : 3
    

    请注意,我的代码根据找到的空格分隔行,而不是使用扫描仪来搜索双精度数/整数。在平面文件中,最好使用格式化标准(空格、逗号、冒号等)而不是格式化文件,这样更容易解析文件。

    编辑

    如果您希望保持平面文件的格式不变,只需将逗号更改为句点即可解决您的问题。我使用了您的功能(将数据库行更改为输出):

    public static void readDatabase(String s) throws IOException {
    
        BufferedReader br = new BufferedReader(new FileReader(s));
        String line = br.readLine();
        Scanner trainFile = null;
        while (line != null) {
            line.trim();
            trainFile = new Scanner(line);
            double x = trainFile.nextDouble();
            double y = trainFile.nextDouble();
            int type = trainFile.nextInt();
            System.out.println(x + " : " + y + " : " + type);
            line = br.readLine();
        }
        trainFile.close();
        br.close();
    }
    

    在文件上(这是您提供的数据,逗号改为句点):

    0.6580097206539348  0.36101701387184226 2
    0.9529350156283241  0.7383387609711926  2
    0.6580097206539348  0.36101701387184226 2
    0.9529350156283241  0.7383387609711926  2
    0.6580097206539348  0.36101701387184226 2
    0.48639272096486486 0.4378985495387871  1
    0.8632344357711337  0.5253407956535258  1
    0.7351912765040557  0.8295830810436339  1
    0.6369155743204543  0.2757349130759706  1
    0.46512947234632146 0.4388586141249502  1
    0.8677892876429869  0.599451235810409   1
    0.8827084731154641  0.55652107505414    1
    

    输出显示正常。

    【讨论】:

    • 非常感谢您的帮助,但出于我计算机上的一个神秘原因:它不适用于点,但是当我更改为逗号时,它确实会读取一些行您所说的相同代码是使用与 ip 相同的文件在此处工作不起作用。
    • 您能给我更多关于您的开发环境的信息吗?您使用的是什么编译器,JDK 版本,您使用的是什么操作系统? Java 是独立的,因此无论您使用的计算机类型如何,它都应该可以正常工作。另外,您是否尝试使用我的代码和我发布的文件?这是一个通用且基本的示例,例如概念证明,然后您可以查看主文件以查看错误所在。
    • 嘿@Mike Elofson,使用你的代码我设法让它正确打印。但是当我尝试在函数内创建一个新点以添加到我的数据库时 - > this.database.add(new Point(x,y,type));保存 3 个变量后,它说我不能在静态上下文中使用它。您对这个问题有什么建议吗?
    • 您可以编辑您的问题并放入堆栈跟踪吗?哪些部分不能在静态上下文中使用?如果是 readDatabase 函数本身,请从函数定义中删除 static 。我需要知道什么不能在静态上下文中使用,然后我很可能会为您提供帮助。
    • 使用您给我的相同代码并放置新的 Point(x,y,type) 而不是 syso 使 Eclipse 点出现错误:不能在静态上下文中使用它。我使用了另一种解决方案,它奏效了。无论如何感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-18
    • 2018-03-09
    • 2012-07-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多