2012-10-24 31 views
35

我是使用Java的新手,但我有一些使用C#的经验。我遇到的问题是从控制台读取用户输入。java.util.NoSuchElementException - 读取用户输入的扫描器

我正在进入 “java.util.NoSuchElementException” 错误与代码的这一部分:

payment = sc.next(); // PromptCustomerPayment function 

我有两个函数获取用户输入:

  • PromptCustomerQty
  • PromptCustomerPayment

如果我不打电话PromptCustomerQty那么我不ge这个错误,这导致我相信我在扫描仪上做错了什么。以下是我的完整代码示例。我感谢任何帮助。

public static void main (String[] args) { 

    // Create a customer 
    // Future proofing the possabiltiies of multiple customers 
    Customer customer = new Customer("Will"); 

    // Create object for each Product 
    // (Name,Code,Description,Price) 
    // Initalize Qty at 0 
    Product Computer = new Product("Computer","PC1003","Basic Computer",399.99); 
    Product Monitor = new Product("Monitor","MN1003","LCD Monitor",99.99); 
    Product Printer = new Product("Printer","PR1003x","Inkjet Printer",54.23); 

    // Define internal variables 
    // ## DONT CHANGE 
    ArrayList<Product> ProductList = new ArrayList<Product>(); // List to store Products 
    String formatString = "%-15s %-10s %-20s %-10s %-10s %n"; // Default format for output 

    // Add objects to list 
    ProductList.add(Computer); 
    ProductList.add(Monitor); 
    ProductList.add(Printer); 

    // Ask users for quantities 
    PromptCustomerQty(customer, ProductList); 

    // Ask user for payment method 
    PromptCustomerPayment(customer); 

    // Create the header 
    PrintHeader(customer, formatString); 

    // Create Body 
    PrintBody(ProductList, formatString); 
} 

public static void PromptCustomerQty(Customer customer, ArrayList<Product> ProductList) { 
    // Initiate a Scanner 
    Scanner scan = new Scanner(System.in); 

    // **** VARIABLES **** 
    int qty = 0; 

    // Greet Customer 
    System.out.println("Hello " + customer.getName()); 

    // Loop through each item and ask for qty desired 
    for (Product p : ProductList) { 

     do { 
     // Ask user for qty 
     System.out.println("How many would you like for product: " + p.name); 
     System.out.print("> "); 

     // Get input and set qty for the object 
     qty = scan.nextInt(); 

     } 
     while (qty < 0); // Validation 

     p.setQty(qty); // Set qty for object 
     qty = 0; // Reset count 
    } 

    // Cleanup 
    scan.close(); 
} 

public static void PromptCustomerPayment (Customer customer) { 
    // Initiate Scanner 
    Scanner sc = new Scanner(System.in); 

    // Variables 
    String payment = ""; 

    // Prompt User 
    do { 
    System.out.println("Would you like to pay in full? [Yes/No]"); 
    System.out.print("> "); 

    payment = sc.next(); 

    } while ((!payment.toLowerCase().equals("yes")) && (!payment.toLowerCase().equals("no"))); 

    // Check/set result 
    if (payment.toLowerCase() == "yes") { 
     customer.setPaidInFull(true); 
    } 
    else { 
     customer.setPaidInFull(false); 
    } 

    // Cleanup 
    sc.close(); 
} 

回答

86

这让我很困惑,但这是我最终发现的。

当您在第一个方法中调用sc.close()时,它不仅会关闭扫描仪,还会关闭您的System.in输入流。

System.out.println(System.in.available()); 

所以,现在当你重新实例在第二种方法,Scanner,它没有找到任何打开System.in流,因此:您可以通过打印其状态在最上面的第二种方法为验证例外。

我,如果有任何出路重新怀疑System.in因为:

public void close() throws IOException --> Closes this input stream and releases any system resources associated with this stream. The general contract of close is that it closes the input stream. A closed stream cannot perform input operations and **cannot be reopened.**

你的问题的唯一好的解决办法是启动Scanner在你的主要方法,传递在你的两个论点

main方法相关的代码块:

Scanner scanner = new Scanner(System.in); 

// Ask users for quantities 
PromptCustomerQty(customer, ProductList, scanner); 

// Ask user for payment method 
PromptCustomerPayment(customer, scanner); 

//close the scanner 
scanner.close(); 
方法,并在你的主要方法如再次关闭种

你的方法:

public static void PromptCustomerQty(Customer customer, 
          ArrayList<Product> ProductList, Scanner scanner) { 

    // no more scanner instantiation 
    ... 
    // no more scanner close 
} 


public static void PromptCustomerPayment (Customer customer, Scanner sc) { 

    // no more scanner instantiation 
    ... 
    // no more scanner close 
} 

希望这为您提供有关故障和可能的解决方案的一些见解。

+4

谢谢你的回应。您对幕后实际发生的情况的解释非常有帮助 – fortune

+0

感谢您的回复。这其实是真的! – d3vpasha

+0

哦,我的天啊,我被困了很久,直到找到这篇文章。非常感谢!你真棒。 –

15

问题是

当扫描仪被关闭时,它会如果源实现Closeable接口,关闭其输入源。

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Scanner.html

因此scan.close()关闭System.in

要解决它,你可以让

Scanner scanstatic 和PromptCustomerQty不要将其关闭。下面的代码工作。

public static void main (String[] args) { 

// Create a customer 
// Future proofing the possabiltiies of multiple customers 
Customer customer = new Customer("Will"); 

// Create object for each Product 
// (Name,Code,Description,Price) 
// Initalize Qty at 0 
Product Computer = new Product("Computer","PC1003","Basic Computer",399.99); 
Product Monitor = new Product("Monitor","MN1003","LCD Monitor",99.99); 
Product Printer = new Product("Printer","PR1003x","Inkjet Printer",54.23); 

// Define internal variables 
// ## DONT CHANGE 
ArrayList<Product> ProductList = new ArrayList<Product>(); // List to store Products 
String formatString = "%-15s %-10s %-20s %-10s %-10s %n"; // Default format for output 

// Add objects to list 
ProductList.add(Computer); 
ProductList.add(Monitor); 
ProductList.add(Printer); 

// Ask users for quantities 
PromptCustomerQty(customer, ProductList); 

// Ask user for payment method 
PromptCustomerPayment(customer); 

// Create the header 
PrintHeader(customer, formatString); 

// Create Body 
PrintBody(ProductList, formatString); 
} 

static Scanner scan; 

public static void PromptCustomerQty(Customer customer, ArrayList<Product> ProductList)    { 
// Initiate a Scanner 
scan = new Scanner(System.in); 

// **** VARIABLES **** 
int qty = 0; 

// Greet Customer 
System.out.println("Hello " + customer.getName()); 

// Loop through each item and ask for qty desired 
for (Product p : ProductList) { 

    do { 
    // Ask user for qty 
    System.out.println("How many would you like for product: " + p.name); 
    System.out.print("> "); 

    // Get input and set qty for the object 
    qty = scan.nextInt(); 

    } 
    while (qty < 0); // Validation 

    p.setQty(qty); // Set qty for object 
    qty = 0; // Reset count 
} 

// Cleanup 

} 

public static void PromptCustomerPayment (Customer customer) { 
// Variables 
String payment = ""; 

// Prompt User 
do { 
System.out.println("Would you like to pay in full? [Yes/No]"); 
System.out.print("> "); 

payment = scan.next(); 

} while ((!payment.toLowerCase().equals("yes")) && (!payment.toLowerCase().equals("no"))); 

// Check/set result 
if (payment.toLowerCase() == "yes") { 
    customer.setPaidInFull(true); 
} 
else { 
    customer.setPaidInFull(false); 
} 
} 

在一个侧面说明,你不应该使用==弦乐对比,使用.equals代替。

+0

但他们在不同的方法是正确的?他们在哪里创建和关闭。 –

+0

它们是原始代码。在固定代码中,我为这两种方法使用一个Scanner实例。 – 2012-10-24 02:25:38

+0

我仍然困惑为什么在第二种方法中sc.next()甚至是sc.nextLine()会导致异常。 –

0

这一行后:

qty = scan.nextInt(); 

务必多加一个线路开通,扫描仪:

scan.nextLine(); 

此外,使用

sc.nextLine(); 

,而不是

sc.next(); 
+0

添加了scan.nextLine();并将sc.next()更改为sc.nextLine();但我仍然收到错误。 – fortune