简体   繁体   English

JAVA:转换包含百分号的字符串时出现NumberFormat异常

[英]JAVA : NumberFormat exception when converting a string containing percent sign

I am using a third party java jar file that convert a string to integer. 我正在使用将字符串转换为整数的第三方Java jar文件。

The jar file is throwing NumberFormatException when the string contains a percent sign "%". 当字符串包含百分号“%”时,jar文件将引发NumberFormatException。

Below is the code of the Jar file. 下面是Jar文件的代码。

String str = "com%paq"; // this is the input string
//the jar file code starts here
byte[] b = new byte[1];
b[0] = (byte)(Integer.parseInt( str.substring( 2, 2 + 2 ), 16 ) & 0xFF);
s[j++] = (new String( b, 0, 1, "ASCII" )).charAt( 0 );

The exception: 例外:

java.lang.NumberFormatException: For input string: "p%"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)

I cannot change the jar file code. 我无法更改jar文件代码。 The above code will always get executed whenever there is a "%" in the string. 只要字符串中有“%”,上述代码就会始终执行。

Is there any way to avoid the exception? 有什么办法可以避免这种异常?

That String has no digits, do the percent character is only part of the problem. 该字符串没有数字,百分比字符只是问题的一部分。 There is no number to parse in str (unless you try to parse only the characters that can be treated as hex digits - c or a - which you don't). 没有数解析str (除非您尝试来解析可以被视为十六进制数字字符- ca -你没有)。

You are trying to parse the substring p% , containing the characters p and % , which are not hexadecimal digits. 您正在尝试分析子字符串p% ,其中包含字符p% ,它们不是十六进制数字。

If you are supplying the input String to the jar, you can verify that the relevant characters are valid digits by validating the input before passing it to the jar. 如果将输入字符串提供给jar,则可以在将输入传递给jar之前验证输入,以验证相关字符是否为有效数字。 You call parseInt yourself, and only pass the String to the jar if you don't get a NumberFormatException . 您自己调用parseInt ,并且仅在未获取NumberFormatException才将String传递给jar。

boolean isValid = true;
String str = "com%paq"; // this is the input string
try {
    int test = Integer.parseInt( str.substring( 2, 2 + 2 ), 16 );
}
catch (NumberFormatException ex) {
    isValid = false;
}
if (isValid) { // invoke the jar code
    //the jar file code starts here
    byte[] b = new byte[1];
    b[0] = (byte)(Integer.parseInt( str.substring( 2, 2 + 2 ), 16 ) & 0xFF);
    s[j++] = (new String( b, 0, 1, "ASCII" )).charAt( 0 );
}

In addition to Erans answer I'd like to point you to the Java API documentation for Integer , which states: 除了Erans答案之外,我还要向您介绍Integer的Java API文档,该文档指出:

An exception of type NumberFormatException is thrown if any of the following situations occurs: 如果发生以下任一情况,将引发NumberFormatException类型的异常:

  • The first argument is null or is a string of length zero. 第一个参数为null或长度为零的字符串。
  • The radix is either smaller than Character.MIN_RADIX or larger than Character.MAX_RADIX. 基数小于Character.MIN_RADIX或大于Character.MAX_RADIX。
  • Any character of the string is not a digit of the specified radix, except that the first character may be a minus sign '-' ('\-') or plus sign '+' ('\+') provided that the string is longer than length 1. 字符串的任何字符都不是指定基数的数字,除非第一个字符可以是减号'-'('\\ u002D')或加号'+'('\\ u002B')(前提是该字符串是长于长度1。
  • The value represented by the string is not a value of type int. 字符串表示的值不是int类型的值。

The radix in the third party code you provided is 16, so it's hexadecimal. 您提供的第三方代码中的基数为16,因此为十六进制。 This would allow the decimal digits 0-9 and letter AF for the passed string. 这将允许十进制数字0-9和字母AF作为传递的字符串。

From what I understood "com%paq" is a string you passed to the third party code yourself and it's not hardcoded in there. 据我了解, "com%paq"是您自己传递给第三方代码的字符串,并且未在其中进行硬编码。 So you have to change it to something valid. 因此,您必须将其更改为有效值。

Integer.parseInt( str.substring( 2, 2 + 2 ), 16 ) evaluation result is "p%" Integer.parseInt( str.substring( 2, 2 + 2 ), 16 )评估结果为"p%"

"p%" is not number, that's why NumberFormatException exception came in your code "p%"不是数字,这就是代码中出现NumberFormatException异常的原因

Interger.parseInt(String str) convert only the string contains digits like "123", "675" etc.. it won't convert character string to integer. Interger.parseInt(String str)仅转换包含“ 123”,“ 675”等数字的字符串。它不会将字符串转换为整数。 if you you want to convert string to integer use String.hashCode(); 如果要将字符串转换为整数,请使用String.hashCode();。 which gives a integer. 给出一个整数。

I can see that this code is trying to convert string to hexa-decimal number . 我可以看到该代码正在尝试将字符串转换为十六进制数字。 as you have used Integer.parseInt("String",radix) . 如您所使用的Integer.parseInt("String",radix)

quickly i tried to run few tests 很快我尝试运行一些测试

  Integer.parseInt("e", 16) ;// prints 14 
  Integer.parseInt("f", 16) ;// prints 15
  Integer.parseInt("g", 16) ;// throws NumberFormat Exception 

basic here is even if you want to convert hexadecmial characters to a number you are limited with characters 'a' ,'b' ... 'f' , if your string contains letters apart from these letter ,it will surely fail with NumberformatException . 即使您想将十六进制字符转换为数字,但您只能将字符'a' ,'b' ... 'f'限制为一个数字,如果您的字符串中除了这些字母之外还包含字母,它肯定会因NumberformatException失败。

as you can see String str = "com%paq" contains invalid letters like m , % , p , q . 如您所见, String str = "com%paq"包含无效的字母,例如m,%,p,q。 so even with substring (2,2+2) will give you m% which is still invalid hexadecimal string. 因此,即使使用substring (2,2+2)也会给您m% ,后者仍然是无效的十六进制字符串。

Is there any way to avoid the exception? 有什么办法可以避免这种异常?

One way could be first validate whether input string has correct characters then only call the method from jar . 一种方法是,首先验证输入字符串是否具有正确的字符,然后仅从jar调用该方法。

for example suppose that the Integer conversion logic is present in getNumber() method in third party jar as shown below . 例如,假设第三方jar的getNumber()方法中存在Integer转换逻辑,如下所示。 (pseudo code for demo purpose) (用于演示目的的伪代码)

public byte[] getNumber(String str){
//the jar file code starts here
byte[] b = new byte[1];
b[0] = (byte)(Integer.parseInt( str.substring( 2, 2 + 2 ), 16 ) & 0xFF);
s[j++] = (new String( b, 0, 1, "ASCII" )).charAt( 0 );
.
.
.
  return b;
}

then put a validation on string before calling to getNumber 然后在调用getNumber之前对字符串进行验证

if(str.matches("^[-+]?[0-9 a-f A-F]+")) //String validation logic .
{
    byte[] b = getNumber(str);
}

this way you can avoid the exception. 这样可以避免异常。

  1. Here you can send custom message if String is not validated 如果未验证String,则可以在此处发送自定义消息

  2. Also you can put more validation on String as per requirement 您还可以根据要求对String进行更多验证

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM