【问题标题】:How to avoid NumberFormatException while using BufferedReader?使用 BufferedReader 时如何避免 NumberFormatException?
【发布时间】:2016-03-24 21:26:13
【问题描述】:

我使用 BufferedReader 从用户那里读取数据,但它给出了 NumberFormat 异常,前提是我以某种方式给出了输入。假设在 C 中,我这样写代码:

scanf("%d %d", &x, &y);

我尝试像这样向控制台提供输入:23 45,它分配的值如下:

x = 23,y = 45

我怎样才能在java中做这样的事情。我试过这样:

BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
BufferedReader br2 = new BufferedReader(new InputStreamReader(System.in));
String line1 = br1.readLine();
String line2 = br2.readLine();
int x = Integer.parseInt(line1);
int y = Integer.parseInt(line2);

但这给出了:

线程“main”java.lang.NumberFormatException 中的异常:对于输入 字符串:“23 45”在 java.lang.NumberFormatException.forInputString(Unknown Source) 在 java.lang.Integer.parseInt(未知来源)在 java.lang.Integer.parseInt(Unknown Source) at AB.main(AB.java:23)

【问题讨论】:

  • 如果我没记错的话,你写的内容被读为一行。试着给它: 23 (enter) 45 如果你想达到这个目的,你必须读一行你想要的所有数字,然后用空格分割这个字符串
  • @user3248186 是只输入一次还是请求两次?
  • readLine 一直读到行尾。在这种情况下,它应该问你两次
  • @Greyshack:我知道它将它作为一行,并且如果我按 Enter 键它就可以工作,但我希望它与空格一起工作,因为这就是它在像 hackerearth 这样的网站上给出的方式。
  • 是的,我告诉过你,你只能读取一行,然后使用 String 的 split() 方法将其拆分,并将 " " 作为拆分的参数传递

标签: java c io bufferedreader


【解决方案1】:

您可以从文件中读取数据并根据 1 个或多个空格分割字符串,并且可以处理多个以空格分隔的输入。

        Scanner s = new Scanner(System.in);
        String line = s.nextLine();
        //String line = "98765432109876543210 9876543210987654321   ";
        String[] splited = line.split("\\s+");

然后比较每个字符串以检查它是否为有效数字。 然后从该数字创建一个新的 BigDecimal。具有内存允许的 64 位 jvm 上的 BigDecimal 最多可以容纳 646456993 位。

        for (int i=0;i<splited.length;i++) {

            if(splited[i].matches("[0-9]*")){

                BigDecimal num = new BigDecimal(splited[i]);
                System.out.println("num "+(i+1)+"="+num);
            }
        }



 Results
 line ="98765432109876543210 9876543210987654321   "
 num 1=98765432109876543210
 num 2=9876543210987654321

 line ="1212312312312312312312313 123432432432432423432423432"
 num 1=1212312312312312312312313
 num 2=123432432432432423432423432

【讨论】:

    【解决方案2】:

    一个 InputStreamReader 就足够了:

       BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
        String line1 = br1.readLine();
        String[] args = line1.split(" ");
    
        if (args.length != 2) {
            throw new IllegalArgumentException("The input is wrong");
        }
    
        int x = getIntFromInput(args[0]);
        int y = getIntFromInput(args[1]);
    

    正如 Jan 指出的那样,您将需要一种转换方法:

    public static int getIntFromInput(String inputString) {
    
        //sanity checks
        if (inputString == null || inputString.trim().length() == 0) {
            throw new IllegalArgumentException("empty or null string passed");
        }
    
        try {
            return new BigInteger(inputString, 10).intValueExact();
        } catch (Exception ignored) {
            throw new IllegalArgumentException(String.format("input string is not a valid integer number: '%s'", inputString));
        }
    }
    

    【讨论】:

    • 嗯......它会仍然抛出 NumberFormatException 输入像1212312312312312312312313 123432432432432423432423432
    • @Jan,不会的 ;)
    • 是的确实如此。试一次。
    • @Jan,请查看 :)
    • 现在它至少不再抛出 NumberFormatExceptions 了。而是 IllegalArgumentExceptions 。不确定这有多大帮助:)
    【解决方案3】:

    现在我们在这里 - 很多很多答案只是解释如何阅读正确输入。但是你会得到NumberFormatExceptions任何其他奇怪的方式。就像你的输入是......

    98765432109876543210 9876543210987654321 
    

    这反过来会抛出NumberFormatException,因为它们太大而无法放入int

    因此,虽然在" " 处拆分并手动寻址令牌是一个不错的建议,但如果仅给出一个 数字,您也会遇到ArrayIndexOutOfBounds

    我的建议是在进一步解析之前检查输入是否看起来有效

    Scanner s = new Scanner(System.in);
    String line = s.nextLine();
    Pattern p = Pattern.compile("(\\d{1,10})\\s+(\\d{1,10})");
    Matcher m = p.matcher(line);
    if(m.matches()) {
      long x1 = Long.parseLong(m.group(1));
      long y1 = Long.parseLong(m.group(2));
      if(x1 <= Integer.MAX_VALUE&& y1 <= Integer.MAX_VALUE) {   
        int x = (int)x1;
        int y = (int)y1;
        System.out.printf("Your input: %d / %d", x, y);
      } else {
        System.err.println("Numbers too big");
      }
    } else {
      System.err.println("Input does not match criteria");
    }
    

    【讨论】:

    • 负数怎么样? :)
    • 对。无论这些数据是否有效,都没有问题的数据。我在这里是一个乐观主义者,只会看到积极的:-)
    【解决方案4】:

    这将解决你的目的

    int x, y;
    String[] input;
      BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
      String str = br.readLine();
      input = str.split(" ");
    
      x = Integer.parseInt(input[0]);
      y = Integer.parseInt(input[1]);
    

    【讨论】:

      【解决方案5】:

      你必须这样做:

      String in = *getline*;
      String[] tab = in.split(' ');
      List<int> nums = new         ArrayList<int>();
      
      for(String a : tab){
      nums.add(Integer.parseInt(a));         // or push() not remember...
      }
      
      // Your nums have your integers now
      

      【讨论】:

        【解决方案6】:

        readLine() 一直读到有换行符为止,通常意味着用户按下了回车键。

        如果你输入 12 34,这是一行,不是像整数那样格式化的一行。

        您可以改用read() 一次读取一个字符,手动拆分行并解析结果,或者最好改用Scanner 类。它有一个更加面向用户 IO 的 api,公开诸如 nextInt()next() (返回下一个“令牌”而不是下一个字符)等方法。

        Scanner in = new Scanner(System.in);
        int x = in.nextInt();
        int y = in.nextInt();
        

        【讨论】:

          【解决方案7】:

          如果你真的想在同一行传递两个参数,请在空格处分割行,然后分别使用每个标记:

          BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
          
          String line1 = br1.readLine();
          
          String[] tokens = line1.split("\\s+") 
          
          int x = Integer.parseInt(tokens[0]);
          int y = Integer.parseInt(tokens[1]);
          

          【讨论】:

            猜你喜欢
            • 2019-10-17
            • 1970-01-01
            • 1970-01-01
            • 2021-01-02
            • 2012-07-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-06-25
            相关资源
            最近更新 更多