Java Integer.valueOf为范围内的有效数字生成NumberFormatException



在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的边界之内。

所以我的问题是,为什么会发生这种情况,我该如何解决?

注意:正如您所看到的,我通过一个解析怪物获得了chunkSizeAsString("8d"),并怀疑其中可能包含不可见的字符。我已经检查了这里提到的"\u200e"one_answers"\u200f",以及这里提到的使用第109行以上的以下加法的"\\p{C}":

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版本"1.7.0_79">

OpenJDK运行时环境(fedora-2.5.5.0.fc20-x86_64 u79-b14)

OpenJDK 64位服务器虚拟机(内部版本24.79-b02,混合模式)

编辑3:根据建议,我做了一些健全性测试:

  • 检查Integer.valueOf("8d", 16)Integer.parseInt("8d", 16)通过的测试
  • chunkSizeAsString.equals("8d")为真
  • chunkSizeAsString.length()=2
  • 字符的整数值为56和100,分别是"8"one_answers"d"的ASCII码

在尝试对其进行一定长度的调试之后,并且考虑到您的更新和堆栈跟踪(事实上您在工作线程上),我确信您在某种程度上将调试尝试与多线程问题混淆了。

将您的代码更改为:

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能够准确地调试/解析导致问题的原因,而不会被假阳性病例所抛弃。

在阅读了所有这些评论后,这里唯一有用的建议是-只需调试它。不用担心,按F7(或其他)进入Integer.valueOf()的实现,这很简单,你会立即看到哪里出了问题。

.valueOf在下面使用.parseInt,您可以执行int chunkSize = Integer.parseInt(chunkSizeAsString, 16);

最新更新