2012-07-18 47 views
2

我開始做簡單的閱讀數據文件的練習。當我運行程序時,數據文件會被讀取,而不是,但由於某種原因,我仍然會得到一個「NoSuchElementException」,並且我的輸出沒有以應有的方式格式化。這裏是正在發生的事情:Java:NoSuchElementException

我創建了一個看起來像這樣一個簡單的數據文件:

Barry Burd 
Author 
5000.00 
Harriet Ritter 
Captain 
7000.00 
Ryan Christman 
CEO 
10000.00 

之後,我寫了一個簡單的「吸氣」和「二傳手」的程序(代碼如下)。

import static java.lang.System.out; 

    //This class defines what it means to be an employee 

public class Employee { 

    private String name; 
    private String jobTitle; 

    public void setName(String nameIn) { 
    name = nameIn; 
    } 

    public String getName() { 
    return name; 
    } 

    public void setJobTitle(String jobTitleIn) { 
    jobTitle = jobTitleIn; 
    } 

    public String getJobTitle() { 
    return jobTitle; 
    } 

    /*The following method provides the method for writing a paycheck*/ 

    public void cutCheck(double amountPaid) { 
    out.printf("Pay to the order of %s ", name); 
    out.printf("(%s) ***$", jobTitle); 
    out.printf("%,.2f\n", amountPaid); 
    } 

} 

夠簡單。 然後我寫了實際使用這個東西的程序(下面的代碼)。

import java.util.Scanner; 
import java.io.File; 
import java.io.IOException; 

public class DoPayroll { 

    public static void main(String[] args) throws IOException { 
    Scanner diskScanner = new Scanner(new File("EmployeeInfo.txt")); 

    for (int empNum = 1; empNum <= 3; empNum++) { 
     payOneEmployee(diskScanner); 
    } 
    } 

    static void payOneEmployee(Scanner aScanner) { 
    Employee anEmployee = new Employee(); 

    anEmployee.setName(aScanner.nextLine()); 
    anEmployee.setJobTitle(aScanner.nextLine()); 
    anEmployee.cutCheck(aScanner.nextDouble()); 
    aScanner.nextLine(); 
    } 
} 

這裏是我的輸出:

Pay to the order of Exception in thread "main" java.util.NoSuchElementException: No line found 
    at java.util.Scanner.nextLine(Scanner.java:1516) 
    at DoPayroll.payOneEmployee(DoPayroll.java:25) 
    at DoPayroll.main(DoPayroll.java:14) 
Barry Burd (Author) ***$5,000.00 
Pay to the order of Harriet Ritter (Captain) ***$7,000.00 
Pay to the order of Ryan Christman (CEO) ***$10,000.00 

編輯我發現了這個問題,但我不明白它大聲笑。顯然,我不得不在數據文件的末尾添加一個空行....爲什麼?

回答

2

我發現了這個問題,但我不明白它大聲笑。顯然,我不得不在數據文件的末尾添加一個空行....爲什麼?

因爲您要告訴Scanner在輸入文件中的工資後面會有回車。但是,對於最後一個條目,沒有回車,因此它確定你已經編寫了一個編程錯誤並拋出了一個未經檢查的異常。

你可以在你的代碼解決這個問題,像這樣:

static void payOneEmployee(Scanner aScanner) { 
    Employee anEmployee = new Employee(); 

    anEmployee.setName(aScanner.nextLine()); 
    anEmployee.setJobTitle(aScanner.nextLine()); 
    anEmployee.cutCheck(aScanner.nextDouble()); 
    if (aScanner.hasNextLine()) { 
     aScanner.nextLine(); 
    } 
} 
1

我認爲它達到了文件的末尾。您應該添加一個while循環:

while(aScanner.hasNext()) { 
    ... 
} 

這樣可以防止掃描儀超過文件末尾。

+0

這其實是一個誤導性的解決方案。只要有掃描儀讀取的任何非空白字符,'hasNext()'就會返回true。這可能會或可能不會以回車結束。如果沒有,代碼仍然會進入while循環,異常仍然會被拋出。 – asteri 2012-07-19 19:21:46

0

這裏的問題是你的文件以字符'0'結尾,而aScanner.nextLine()試圖消耗換行符('\ n')。

現在,這裏有趣的事情是彈出的例外。它似乎在打印的第一個cutCheck()的中間。我的猜測是它與IO緩衝和輸出流的異步性有關。 out.printf()是stdout,而錯誤信息是在stderr上發生的,因此可以解釋那裏的奇怪行爲。

如果你把Thread.sleep()放在for循環中,這可能會清除打印問題(儘管這顯然只是一種好奇心,而不是修復你的代碼或類似的東西)。

+0

絕對奇怪的是,錯誤是在輸出的中間。 – 2012-07-18 19:55:05

+0

嘗試添加Thread.sleep()檢查。我想我以前曾經見過這樣的事情,它肯定會使解析調試輸出變得混亂 – mfrankli 2012-07-18 19:58:18

0

你應該調用aScanner.nextLine之前調用hasNextLine()。 您正在嘗試在文件末尾讀取沒有一行的行。

2

每次撥打電話payOneEmployee()最後撥打aScanner.nextLine()。這包括您最後一次呼叫它的時間(在for循環中empNum等於3時)。當文件中沒有更多新行(\n)並且您仍然調用nextLine()時,您收到NoSuchElementException,因爲......呃......沒有這樣的元素。這是因爲文件中的最後一個元素是0字符。

爲了避免將來出現這種情況,您可以添加一個簡單的檢查器。 java.util.Scanner已經爲您執行了hasNextLine()。因此,你可以簡單地改變

aScanner.nextLine(); 

...到...

if(aScanner.hasNextLine()) aScanner.nextLine();