使用 Scanner.useDelimiter() 和 hasNextLine() 从文件中读取 - NoSuchElementException

发布于 2025-01-15 16:21:43 字数 1223 浏览 9 评论 0原文

当我尝试从 textfile 加载数据时,使用这样的数据,

java;sdf;2.0;3.0;
cpp;sdks;24.6;89.0;

我将通过此代码得到 NoSuchElementException

public void loadFile() {
  Scanner scan = null;  
  int n = 0;
  try {
     scan = new Scanner(new File(this.filename)).useDelimiter(";");
     this.items.clear();
     
     while (scan.hasNextLine()) {
        String name = scan.next();
        String barcode = scan.next();
        double unitPrice = scan.nextDouble();
        double shipCost = scan.nextDouble();

        Product newProduct = new Product(name, barcode, unitPrice, shipCost);
        this.items.add(newProduct);
        n++;
     }
  } 
  catch (IOException e) {
     System.err.println("Caught IOException: " + e.getMessage());
  } catch (InputMismatchException e) {
     System.err.println("Caught InputMismatchException: " + e.getMessage());
     System.out.println(n + " products loaded!");
  } catch (NoSuchElementException e) {
     System.err.println("Attempt to read past end of file");
  } catch (IllegalStateException e) {
     System.err.println("Attempt to read a closed file");
  } finally {
     if (scan != null)
        scan.close();
  }
}

When I try to load the data from the textfile, with data like this

java;sdf;2.0;3.0;
cpp;sdks;24.6;89.0;

I'm getting the NoSuchElementException with this code.

public void loadFile() {
  Scanner scan = null;  
  int n = 0;
  try {
     scan = new Scanner(new File(this.filename)).useDelimiter(";");
     this.items.clear();
     
     while (scan.hasNextLine()) {
        String name = scan.next();
        String barcode = scan.next();
        double unitPrice = scan.nextDouble();
        double shipCost = scan.nextDouble();

        Product newProduct = new Product(name, barcode, unitPrice, shipCost);
        this.items.add(newProduct);
        n++;
     }
  } 
  catch (IOException e) {
     System.err.println("Caught IOException: " + e.getMessage());
  } catch (InputMismatchException e) {
     System.err.println("Caught InputMismatchException: " + e.getMessage());
     System.out.println(n + " products loaded!");
  } catch (NoSuchElementException e) {
     System.err.println("Attempt to read past end of file");
  } catch (IllegalStateException e) {
     System.err.println("Attempt to read a closed file");
  } finally {
     if (scan != null)
        scan.close();
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冷情 2025-01-22 16:21:43

hasNextLine() 方法等待直到没有 nextLine
但 hasNext() 会等到有下一个令牌

对于解决方案的角度使用:

 while (scan.hasNext()) {
            String name = scan.next();
            String barcode = scan.next();
            double unitPrice = scan.nextDouble();
            double shipCost = scan.nextDouble();

            System.out.println(name);

            n++;
         }

这将解决您的问题

hasNextLine() method waits unitl there is no nextLine
but hasNext() waits until there is next token

For solution perspective use :

 while (scan.hasNext()) {
            String name = scan.next();
            String barcode = scan.next();
            double unitPrice = scan.nextDouble();
            double shipCost = scan.nextDouble();

            System.out.println(name);

            n++;
         }

This will solve your problem

手心的海 2025-01-22 16:21:43

有几种方法可以解决这个问题。

1.当前行上的所有标记都已读取后,前进到下一行。

为此,请在循环末尾添加行scan.nextLine()。方法 nextLine() 将返回整个当前行(该值将被省略),并将扫描仪位置设置在下一行的开头。

while (scan.hasNextLine()) {
    // reading tokens and creating new Product

    scan.nextLine();
}

2. while循环中的条件更改为scan.hasNext()。这样它就会检查是否存在更多令牌。

但是会出现另一个问题:从第二个item开始,所有item名称都将在开头包含一个换行符(\n)。

要处理它,您可以对名称应用strip(),将分隔符更改为"[;\\r\\n]+"(使用每个换行符\n和回车符\r` 字符以及分号都将被省略

can = new Scanner(new File(this.filename)).useDelimiter("[;\\r\\n]+");
this.items.clear();
            
while (scan.hasNext()) {
    // code inside the loop remains the same
}

这种方法的缺点:条件。 scan.hasNext() 检查单个令牌是否存在没有清楚地表明读取由四个标记组成的行的意图

3。最后一个选项是使用 scan.nextLine() 逐行读取文件。然后对其应用 split(";") ,这将给出一个字符串数组。

这个解决方案可能看起来有点乏味,因为它需要处理拆分来解析 double< /code> 值手动

while (scan.hasNextLine()) {
    String[] line = scan.nextLine().split(";");
    String name = line[0];
    String barcode = line[1];
    double unitPrice = Double.parseDouble(line[2]);
    double shipCost = Double.parseDouble(line[3]);

    Product newProduct = new Product(name, barcode, unitPrice, shipCost);
    this.items.add(newProduct);
}

测试上述所有解决方案 。 file-example 和一个虚拟 Product

Outputitems 列表内容) 。

[Product{name='java', barcode='sdf', unitPrice=2.0, shipCost=3.0}, Product{name='cpp', barcode='sdks', unitPrice=24.6, shipCost=89.0}]

There are several approaches how you can solve this.

1. Advance to the next line when all token on the current line have been read.

For that, add the line scan.nextLine() at the end of the loop. Method nextLine() will return the whole current line (that value will be omitted) and will set the scanners position at the beginning of the next line.

while (scan.hasNextLine()) {
    // reading tokens and creating new Product

    scan.nextLine();
}

2. Change the condition in the while loop to scan.hasNext(). So that it'll check whether more token exists.

But another problem will arise: stating from the second item all item names will contain a new line character (\n) at the beginning.

To handle it, you can either apply strip() on a name, change the delimiter to "[;\\r\\n]+" (with that every new line character\nand carriage return\r` character as well as semicolon will be omitted.

can = new Scanner(new File(this.filename)).useDelimiter("[;\\r\\n]+");
this.items.clear();
            
while (scan.hasNext()) {
    // code inside the loop remains the same
}

The drawback of this approach: condition scan.hasNext() that check existence of a single token doesn't clearly show the intention to read the line comprised of four tokens.

3. The last option is to read the file line by line with scan.nextLine() and then apply split(";") on it, which will give an array of strings.

This solution might look a bit more tedious because it'll require to handle the splitting to parse double values manually.

while (scan.hasNextLine()) {
    String[] line = scan.nextLine().split(";");
    String name = line[0];
    String barcode = line[1];
    double unitPrice = Double.parseDouble(line[2]);
    double shipCost = Double.parseDouble(line[3]);

    Product newProduct = new Product(name, barcode, unitPrice, shipCost);
    this.items.add(newProduct);
}

All solutions above are tested with the provided file-example and a dummy Product class.

Output (items list contents)

[Product{name='java', barcode='sdf', unitPrice=2.0, shipCost=3.0}, Product{name='cpp', barcode='sdks', unitPrice=24.6, shipCost=89.0}]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文