Java Integer.valueOf 为范围内的有效数字生成 NumberFormatException
Java Integer.valueOf produces NumberFormatException for valid number within range
在Java,我打电话:
String chunkSizeAsString = responseString.split(DOUBLE_NEW_LINE)[1]
.split(SINGLE_NEW_LINE)[0];
System.out.println("Trying to get integer value of '" + chunkSizeAsString + "'");
Integer chunkSize = Integer.valueOf(chunkSizeAsString, 16); // this is line 109
并得到输出:
Trying to get integer value of '8d'
Exception in thread "Thread-2" java.lang.NumberFormatException: For input string: "8d"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:481)
at java.lang.Integer.valueOf(Integer.java:556)
at ProxyWorker.handleRequest(ProxyWorker.java:109)
at ProxyWorker.run(ProxyWorker.java:41)
at java.lang.Thread.run(Thread.java:745)
所以基本上,我打电话给 Integer.valueOf("8d", 16)
并收到一个 NumberFormatException
。我见过很多例子,其中 OP 忘记指定正确的基数,或者结果数字超出了 Integer、Long 等的范围。但是 0x8d = 141,这在 Integer 的范围内很舒服。
所以我的问题是,为什么会发生这种情况,我该如何解决?
N.B。如您所见,我正在通过一个异常的解析得到 chunkSizeAsString
("8d"),并且怀疑可能涉及不可见的字符。我已经使用第 109 行上方的以下添加项检查了 here, and "\p{C}" as mentioned here 中提到的“\u200e”和“\u200f”:
chunkSizeAsString = chunkSizeAsString.replaceAll("\u200e", "");
chunkSizeAsString = chunkSizeAsString.replaceAll("\u200f", "");
chunkSizeAsString = chunkSizeAsString.replaceAll("[^\p{Print}]", "");
但这并没有改变输出。
编辑:
我正在使用 jdk1.7.0_7,供应商是 'Oracle Corporation'。 谢谢 fge。
编辑 2:
将 jdk 更新为 1.7u79 并意识到我需要从我正在 运行 和测试的服务器获取 java 供应商,而不是我的家庭开发环境:
java version "1.7.0_79"
OpenJDK Runtime Environment (fedora-2.5.5.0.fc20-x86_64 u79-b14)
OpenJDK 64-Bit Server VM (build 24.79-b02, mixed mode)
编辑 3:
根据建议,我做了一些完整性测试:
- 检查
Integer.valueOf("8d", 16)
和 Integer.parseInt("8d", 16)
的测试通过
chunkSizeAsString.equals("8d")
为真
chunkSizeAsString.length()
= 2
- 字符的整数值为56和100,分别是“8”和"d"的ASCII码
.valueOf
在下面使用 .parseInt
,你可以做 int chunkSize = Integer.parseInt(chunkSizeAsString, 16);
阅读所有这些评论后,这里唯一有用的建议可能是 - 调试。不用担心,按 F7(或其他)进入 Integer.valueOf()
的实现,非常简单,您将立即 看看哪里出了问题。
在尝试对此进行了一定程度的调试之后,并且考虑到您的更新和堆栈跟踪(您在工作线程上的事实),我相信您在某种程度上将调试尝试与多线程问题。
将您的代码更改为:
private final AtomicInteger attemptCounter = new AtomicInteger(0);
void whateverYourMethodIsCalled(String responseString) {
int attemptId = attemptCounter.incrementAndGet();
System.out.format("Beginning attempt: %d%n", attemptId);
String chunkSizeAsString = responseString.split(DOUBLE_NEW_LINE)[1]
.split(SINGLE_NEW_LINE)[0];
System.out.format("In attempt %d, trying to get integer value of '%s', which is length %d%n",
attemptId, chunkSizeAsString, chunkSizeAsString.length());
Integer chunkSize = Integer.valueOf(chunkSizeAsString, 16); // this is line 109
System.out.format("Ending attempt: %d%n", attemptId);
}
最有可能发生的情况是,您第一次尝试工作正常,通过了调试用例,然后在稍后处理的 String
中抛出了错误。
对评论的回应:似乎正在发生的事情是,最初的提问者正在处理大量数据和大量案例。在一个特定的案例中,他得到了不可见的字符,但那不是问题发生的 第一次 时间,他混淆了问题与哪个特定案例是那个抛出问题。通过隔离产生问题的解析数据,@Tait 能够准确地调试/解析导致问题的原因,而不会被误报案例所抛弃。
在Java,我打电话:
String chunkSizeAsString = responseString.split(DOUBLE_NEW_LINE)[1]
.split(SINGLE_NEW_LINE)[0];
System.out.println("Trying to get integer value of '" + chunkSizeAsString + "'");
Integer chunkSize = Integer.valueOf(chunkSizeAsString, 16); // this is line 109
并得到输出:
Trying to get integer value of '8d'
Exception in thread "Thread-2" java.lang.NumberFormatException: For input string: "8d"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:481)
at java.lang.Integer.valueOf(Integer.java:556)
at ProxyWorker.handleRequest(ProxyWorker.java:109)
at ProxyWorker.run(ProxyWorker.java:41)
at java.lang.Thread.run(Thread.java:745)
所以基本上,我打电话给 Integer.valueOf("8d", 16)
并收到一个 NumberFormatException
。我见过很多例子,其中 OP 忘记指定正确的基数,或者结果数字超出了 Integer、Long 等的范围。但是 0x8d = 141,这在 Integer 的范围内很舒服。
所以我的问题是,为什么会发生这种情况,我该如何解决?
N.B。如您所见,我正在通过一个异常的解析得到 chunkSizeAsString
("8d"),并且怀疑可能涉及不可见的字符。我已经使用第 109 行上方的以下添加项检查了 here, and "\p{C}" as mentioned here 中提到的“\u200e”和“\u200f”:
chunkSizeAsString = chunkSizeAsString.replaceAll("\u200e", "");
chunkSizeAsString = chunkSizeAsString.replaceAll("\u200f", "");
chunkSizeAsString = chunkSizeAsString.replaceAll("[^\p{Print}]", "");
但这并没有改变输出。
编辑:
我正在使用 jdk1.7.0_7,供应商是 'Oracle Corporation'。 谢谢 fge。
编辑 2: 将 jdk 更新为 1.7u79 并意识到我需要从我正在 运行 和测试的服务器获取 java 供应商,而不是我的家庭开发环境:
java version "1.7.0_79"
OpenJDK Runtime Environment (fedora-2.5.5.0.fc20-x86_64 u79-b14)
OpenJDK 64-Bit Server VM (build 24.79-b02, mixed mode)
编辑 3: 根据建议,我做了一些完整性测试:
- 检查
Integer.valueOf("8d", 16)
和Integer.parseInt("8d", 16)
的测试通过 chunkSizeAsString.equals("8d")
为真chunkSizeAsString.length()
= 2- 字符的整数值为56和100,分别是“8”和"d"的ASCII码
.valueOf
在下面使用 .parseInt
,你可以做 int chunkSize = Integer.parseInt(chunkSizeAsString, 16);
阅读所有这些评论后,这里唯一有用的建议可能是 - 调试。不用担心,按 F7(或其他)进入 Integer.valueOf()
的实现,非常简单,您将立即 看看哪里出了问题。
在尝试对此进行了一定程度的调试之后,并且考虑到您的更新和堆栈跟踪(您在工作线程上的事实),我相信您在某种程度上将调试尝试与多线程问题。
将您的代码更改为:
private final AtomicInteger attemptCounter = new AtomicInteger(0);
void whateverYourMethodIsCalled(String responseString) {
int attemptId = attemptCounter.incrementAndGet();
System.out.format("Beginning attempt: %d%n", attemptId);
String chunkSizeAsString = responseString.split(DOUBLE_NEW_LINE)[1]
.split(SINGLE_NEW_LINE)[0];
System.out.format("In attempt %d, trying to get integer value of '%s', which is length %d%n",
attemptId, chunkSizeAsString, chunkSizeAsString.length());
Integer chunkSize = Integer.valueOf(chunkSizeAsString, 16); // this is line 109
System.out.format("Ending attempt: %d%n", attemptId);
}
最有可能发生的情况是,您第一次尝试工作正常,通过了调试用例,然后在稍后处理的 String
中抛出了错误。
对评论的回应:似乎正在发生的事情是,最初的提问者正在处理大量数据和大量案例。在一个特定的案例中,他得到了不可见的字符,但那不是问题发生的 第一次 时间,他混淆了问题与哪个特定案例是那个抛出问题。通过隔离产生问题的解析数据,@Tait 能够准确地调试/解析导致问题的原因,而不会被误报案例所抛弃。