java 使用Scanner时InputMismatchException的问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2708186/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 22:26:39  来源:igfitidea点击:

Question about InputMismatchException while using Scanner

java

提问by user325045

The question :

问题:

Input file:customer's account number, account balance at beginning of month, transaction type (withdrawal, deposit, interest), transaction amount

输入文件:客户账号、月初账户余额、交易类型(取款、存款、利息)、交易金额

Output:account number, beginning balance, ending balance, total interest paid, total amount deposited, number of deposits, total amount withdrawn, number of withdrawals

输出:帐号,期初余额,期末余额,支付的利息总额,存款总额,存款数量,取款总额,取款数量

package sentinel;

import java.io.*;
import java.util.*;

public class Ex7 {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws FileNotFoundException
 {
        int AccountNum;
        double BeginningBalance;
        double TransactionAmount;
        int TransactionType;
        double AmountDeposited=0;
        int NumberOfDeposits=0;
        double InterestPaid=0.0;
        double AmountWithdrawn=0.0;
        int NumberOfWithdrawals=0;
        boolean found= false;

        Scanner inFile = new Scanner(new FileReader("Account.in"));
        PrintWriter outFile = new PrintWriter("Account.out");

           AccountNum = inFile.nextInt();
           BeginningBalance= inFile.nextDouble();

           while (inFile.hasNext())
        {
               TransactionAmount=inFile.nextDouble();
               TransactionType=inFile.nextInt();
                outFile.printf("Account Number: %d%n", AccountNum);
                outFile.printf("Beginning Balance: $%.2f %n",BeginningBalance);
                outFile.printf("Ending Balance: $%.2f %n",BeginningBalance);
                outFile.println();
               switch (TransactionType)
            {
                   case '1': // case 1 if we have a Deposite
                BeginningBalance = BeginningBalance
                        + TransactionAmount;
                AmountDeposited = AmountDeposited
                        + TransactionAmount;
                NumberOfDeposits++;
                outFile.printf("Amount Deposited: $%.2f %n",AmountDeposited);
                outFile.printf("Number of Deposits: %d%n",NumberOfDeposits);
                outFile.println();

                break;
                   case '2':// case 2 if we have an Interest
                BeginningBalance = BeginningBalance
                        + TransactionAmount;
                InterestPaid = InterestPaid
                        + TransactionAmount;
                outFile.printf("Interest Paid: $%.2f %n",InterestPaid);
                outFile.println();

                break;

                   case '3':// case 3 if we have a Withdraw
                BeginningBalance = BeginningBalance
                        - TransactionAmount;
                AmountWithdrawn = AmountWithdrawn
                        + TransactionAmount;
                NumberOfWithdrawals++;
                outFile.printf("Amount Withdrawn: $%.2f %n",AmountWithdrawn);
                outFile.printf("Number of Withdrawals: %d%n",NumberOfWithdrawals);
                outFile.println();

                    break;

                default:
                System.out.println("Invalid transaction Tybe: " + TransactionType
                        + TransactionAmount);

               }
           }
           inFile.close();
           outFile.close();
    }
}

But is gives me this :

但是给了我这个:

Exception in thread "main" java.util.InputMismatchException
        at java.util.Scanner.throwFor(Scanner.java:840)
        at java.util.Scanner.next(Scanner.java:1461)
        at java.util.Scanner.nextInt(Scanner.java:2091)
        at java.util.Scanner.nextInt(Scanner.java:2050)
        at sentinel.Ex7.main(Ex7.java:36)
Java Result: 1

回答by JRL

This is how I would proceed:

这就是我将继续的方式:

  • look up what that Exception means in the API documentation.
  • think of how it could happen, what line it happens on (look at your stack trace). If you don't know how to read the stacktrace, here's a tutorial.
  • if you can't immediately see the reason, set a breakpoint and run it through your debugger to "visualize" the current state of your program before the exception happens.
  • API 文档中查找该异常的含义。
  • 想想它是如何发生的,它发生在哪一行(看看你的堆栈跟踪)。如果你不知道如何阅读堆栈跟踪,这里有一个教程
  • 如果您不能立即看到原因,请设置一个断点并通过调试器运行它以在异常发生之前“可视化”程序的当前状态。

You might not know how to use your debugger yet, and while some might not agree, I think it's never too early. There are some excellent video tutorials on how to use the debugger here. Good luck!

你可能还不知道如何使用你的调试器,虽然有些人可能不同意,但我认为永远不会太早。对于如何使用调试器的一些优秀的视频教程在这里。祝你好运!

回答by Anton Guryanov

I guess it is a little too late to answer this question, but I recently stumbled upon the same problem, and my googling led me here.

我想现在回答这个问题有点晚了,但我最近偶然发现了同样的问题,我的谷歌搜索把我带到了这里。

I think the most common case for InputMismatchExceptionthrown by Scanner.nextDouble()is that your default locale used by your Scannerexpects doubles in different format (for example, 10,5, not 10.5). If that is the case, you should use Scanner.useLocalemethod like this

我认为最常见的InputMismatchException抛出的情况Scanner.nextDouble()是您Scanner期望使用的默认语言环境以不同的格式(例如,10,5, not 10.5)。如果是这种情况,你应该使用这样的Scanner.useLocale方法

Scanner s = new Scanner(System.in);
s.useLocale(Locale.US);

回答by extraneon

I don't particularly like the design, all in one, as it goes against the strengths of Java, a bit of object orientation. So I rewrote the program along the lines I think.

我不是特别喜欢这种设计,因为它违背了 Java 的优势,有点面向对象。所以我按照我的想法重写了程序。

I also figured out that interpreting doubles is locale dependent, on my machine a double (in a string) should have a comma (12,12) and not a point (12.12), so that may be your problem.

我还发现解释双打取决于语言环境,在我的机器上,双打(在字符串中)应该有一个逗号(12,12)而不是一个点(12.12),所以这可能是你的问题。

And as said by polygenelubricants, member and method names are lower cased in Java, only types use Capitalization.

正如 polygenelubricants 所说,成员和方法名称在 Java 中是小写的,只有类型使用大写。

I added my own implementation not because yours didn't work, but to show how you could delegate responsibilities to classes which reflect the problem domain, making the code a bit more readable (though considerably longer with boilerplate getters and setters).

我添加了自己的实现并不是因为你的实现不起作用,而是为了展示如何将职责委派给反映问题域的类,使代码更具可读性(尽管使用样板 getter 和 setter 的时间要长得多)。

My implementation of your program would be something like:

我对你的程序的实现是这样的:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.PrintWriter;
import java.util.Scanner;

public class Ex7 {
    /**
     * One transaction record in the file Should be format "int double\n"
     * Note that interpreting a double is locale dependent, on my machine
     * I need "12,24" whereas a US locale might require "12.24"
     */
    public static class Transaction {
        double amount;
        int type; // Prefer an enum here...

        public void read(Scanner scanner) {
            setAmount(scanner.nextDouble());
            setType(scanner.nextInt());
        }

        public int getType() {
            return type;
        }

        public void setType(int type) {
            this.type = type;
        }

        public double getAmount() {
            return amount;
        }

        public void setAmount(double amount) {
            this.amount = amount;
        }

        @Override
        public String toString() {
            return String.format("Transaction(type=%d, amount=%.2f)", type, amount);
        }
    }

    /**
     * Account information and processing Account file format: Line 1
     * "int double\n" account number start balance Line 2-... "double int\n"
     * transaction amount transaction type.
     * Type 1=deposit, 2=interest
     * 3=withdrawal
     */
    public static class Account {
        int accountNum;
        double startBalance;
        double currentBalance;
        double totalDeposited;
        double totalWithdrawn;
        double totalInterestPaid;
        int numberOfDeposits;
        int numberOfWithdrawals;
        int numberOfInterestPayments;

        public Account(Scanner scanner) {
            read(scanner);
        }

        private void read(Scanner scanner) {
            setAccountNum(scanner.nextInt());
            setStartBalance(scanner.nextDouble());
            setCurrentBalance(getStartBalance());
        }

        public int getAccountNum() {
            return accountNum;
        }

        public void setAccountNum(int accountNum) {
            this.accountNum = accountNum;
        }

        public double getStartBalance() {
            return startBalance;
        }

        public void setStartBalance(double startBalance) {
            this.startBalance = startBalance;
        }

        public double getCurrentBalance() {
            return currentBalance;
        }

        public void setCurrentBalance(double currentBalance) {
            this.currentBalance = currentBalance;
        }

        public void processTransaction(Transaction transaction) {
            switch (transaction.getType()) {
            case 1:
                handleDeposit(transaction.getAmount());
                break;
            case 2: // Isn't this just a deposit?
                handleInterest(transaction.getAmount());
                break;
            case 3:
                handleWithdraw(transaction.getAmount());
                break;
            default:
                throw new RuntimeException("Can not process transaction " + transaction + ", transaction type unknown.");
            }
        }

        private void handleDeposit(double deposit) {
            numberOfDeposits++;
            currentBalance += deposit;
            totalDeposited += deposit;
        }

        private void handleInterest(double interestPaid) {
            numberOfInterestPayments++;
            currentBalance += interestPaid;
            totalInterestPaid += interestPaid;
        }

        private void handleWithdraw(double amountWithdrawn) {
            numberOfWithdrawals++;
            currentBalance -= amountWithdrawn;
            totalWithdrawn += amountWithdrawn;
        }

        public String getOverview() {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("Total Deposited : " + totalDeposited).append("\n");
            stringBuilder.append("Total Withdrawn : " + totalWithdrawn).append("\n");
            stringBuilder.append("Total Interest  : " + totalInterestPaid).append("\n");
            stringBuilder.append("Current Balance : " + currentBalance).append("\n").append("\n");
            return stringBuilder.toString();
        }

    }

    /**
     * @param args
     *            the command line arguments
     */
    public static void main(String[] args) throws FileNotFoundException {

        Scanner inFile = null;
        PrintWriter outFile= null;
        try {
            inFile = new Scanner(new FileReader("Account.in"));
            outFile = new PrintWriter("Account.out");

            Account account;
            try {
                account = new Account(inFile);
            } catch (RuntimeException e) {
                // Catch exception for error message display
                System.err.println("Could not read account information from file. Quitting");
                System.exit(1);
                return; // Otherwise compiler error :)
            }

            int lineNumber = 1; // Start with 1 because first line has account info
            while (inFile.hasNext()) {
                Transaction transaction = new Transaction();
                try {
                    transaction.read(inFile);
                } catch (RuntimeException e) {
                    System.err.println("An error ocurred while processing a transaction on line " + lineNumber + ". Transaction " + transaction + " incomplete and failed");
                    throw e; // rethrow and let the stack trace shine!
                }
                lineNumber++;

                outFile.printf("Account Number: %d%n", account.getAccountNum());
                outFile.printf("Beginning Balance: $%.2f %n", account.getStartBalance());
                outFile.printf("Current Balance: $%.2f %n", account.getCurrentBalance());
                outFile.println();

                account.processTransaction(transaction);
                outFile.print(account.getOverview());

            }
        } finally {
            if (inFile != null) {
                inFile.close(); // This can also yield an exception, but I just don't care anymore :)
            }
            if (outFile != null) {
                outFile.close();
            }
        }
    }
}

回答by Xavier Ho

If you read the Exceptionmessages, it's an InputMismatchException. This is highly likely caused by the nextDouble()or nextInt()function, when it's not reading the correct type. Make sure your data is aligned correctly, and you're not reading doubles with readInt().

如果您阅读Exception消息,则是InputMismatchException. 这很可能是由nextDouble()ornextInt()函数导致的,因为它没有读取正确的类型。确保您的数据正确对齐,并且您没有使用readInt().

回答by polygenelubricants

You may want to include the content of Account.into provide more information, but here are some comments:

您可能希望包含 的内容Account.in以提供更多信息,但这里有一些评论:

Naming conventions

命名约定

Variables: Except for variables, all instance, class, and class constants are in mixed case with a lowercase first letter.

变量:除变量外,所有实例、类和类常量都是大小写混合的,首字母小写

This means that by convention, the variable names should be upper/lower-cased like accountNum, beginningBalance, numberOfDeposits, etc.

这意味着,按照惯例,变量名应该是上/小写等accountNumbeginningBalancenumberOfDeposits等。

It should also be mentioned that the way you're placing your curly braces are highly unconventional. It may be a good idea for you to learn good coding style.

还应该提到的是,您放置花括号的方式非常非常规。学习良好的编码风格对您来说可能是个好主意。



This part is also highly inconsistent:

这部分也是高度不一致的:

int TransactionType; // declared as int
//...
TransactionType=inFile.nextInt(); // read as int
//...
switch (TransactionType)
   case '1': // used as ... char? ASCII '1' = 49

I'm 99% certain that you really need to switchon case 1:, case 2:, case 3:instead.

我99%肯定,你真正需要switchcase 1:case 2:case 3:来代替。



You may also want to print the ending balance AFTERyou processed the transaction. Right now, you'll always print the same numbers for beginning and ending balance.

您可能还想在处理交易打印期末余额。现在,您将始终为期初余额和期末余额打印相同的数字。

It may also benefit you to know that Java has "compound assignment" operators that would make your code a lot more readable. You probably need not concern yourself with the exact semantics right now, but basically instead of this:

知道 Java 具有“复合赋值”运算符可能会让您受益,这将使您的代码更具可读性。您现在可能不需要关心确切的语义,但基本上不是这样:

            BeginningBalance = BeginningBalance
                    + TransactionAmount;

            BeginningBalance = BeginningBalance
                    - TransactionAmount;

You can instead write:

你可以写:

beginningBalance += transactionAmount;

beginningBalance -= transactionAmount;


Finally, one last comment about the InputMismatchException: others have already explained to you what this means. My best guess right now is that your problem is caused by this:

最后,关于 的最后一条评论InputMismatchException:其他人已经向您解释了这意味着什么。我现在最好的猜测是您的问题是由以下原因引起的:

Input file: customer's account number, account balance at beginning of month, transaction type (withdrawal, deposit, interest), transaction amount

输入文件:客户账号、月初账户余额、交易类型(取款、存款、利息)、交易金额

vs:

对比:

           TransactionAmount=inFile.nextDouble();
           TransactionType=inFile.nextInt();

I need to see Account.into confirm, but I suspect that the inttransaction type appears before the doubletransaction amount, just like the problem statement says. Your code reads them in the opposite order.

需要查看Account.in确认,但我怀疑int交易类型出现在double交易金额之前,就像问题陈述所说的那样。您的代码以相反的顺序读取它们。

This would attempt to read the intas nextDouble(), which is okay, but the doubleas nextInt()would throw InputMismatchException.

这将尝试读取intas nextDouble(),这是可以的,但doubleasnextInt()会抛出InputMismatchException