web-dev-qa-db-ja.com

java.util.NoSuchElementException-スキャナー読み取りユーザー入力

私はJavaを使用するのは初めてですが、C#の以前の経験があります。私が抱えている問題は、コンソールからのユーザー入力の読み取りに伴います。

コードの次の部分で「Java.util.NoSuchElementException」エラーが発生しています。

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

ユーザー入力を取得する2つの関数があります。

  • PromptCustomerQty
  • PromptCustomerPayment

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);   
}

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(); 
}
50
fortune

これはしばらくの間私を本当に困惑させましたが、これは私が最後に見つけたものです。

最初のメソッドでsc.close()を呼び出すと、スキャナーを閉じるだけでなく、_System.in_入力ストリームも閉じます。次のように、2番目のメソッドの一番上にステータスを出力することで確認できます。

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

したがって、2番目のメソッドで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を開始し、それを2つのメソッドの引数として渡し、メインメソッドで再度閉じることです:

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
 }
_

これにより、障害と可能な解決策についての洞察が得られることを願っています。

118
Yogendra Singh

問題は

スキャナーが閉じられると、ソースが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を使用してください。

18
user1766873