ASCII字符数组与long类型互转在值128处失败的问题解决
ASCII字符数组与long类型互转的问题解决
问题背景
我实现了将ASCII字符数组转换为long类型、以及long类型转换为ASCII字符数组的Java方法,但在处理值128时转换失败。
错误实现代码
最初的转换方法依赖字符编码/解码实现:
public long asciiToLong(char[] in) { CharBuffer charBuffer = CharBuffer.wrap(in); ByteBuffer byteBuffer = StandardCharsets.US_ASCII.encode(charBuffer); byte[] byteArray = new byte[byteBuffer.remaining()]; byteBuffer.get(byteArray); long result = ByteBuffer.wrap(new String(byteArray).getBytes()).getLong(); return result; } public char[] longToAscii(long in) { ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); buffer.putLong(in); byte[] b = buffer.array(); CharBuffer charBuffer = StandardCharsets.US_ASCII.decode(ByteBuffer.wrap(b)); char[] result = new char[charBuffer.remaining()]; charBuffer.get(result); return result; }
测试代码及失败结果
使用以下循环测试时,在值128处出现转换错误:
for (long l = 0 ; l < 100000 ; l++) { char[] ascii = longToAscii(l); System.out.printf("%d -> ", l); long l2 = asciiToLong(ascii); System.err.printf("%d\n", l2); if (l != l2) { throw new RuntimeException(); } }
输出结果(部分):
0 -> 0 1 -> 1 2 -> 2 3 -> 3 // 中间输出省略.. 126 -> 126 127 -> 127 128 -> 63 // 转换失败
更换解码用的StandardCharset后,仍在同一位置失败,仅错误结果值不同。
问题原因
US_ASCII字符集仅支持0-127的字符范围,当处理值为128的字节(超出ASCII范围)时,编码/解码过程会自动将其替换为替换字符63(即'?'),导致原始数值信息丢失。本质上,这里误用了字符编码转换来处理原始字节数据——需求是直接将字节与char做数值映射,而非进行字符编码的编解码。
正确实现(无编码方式)
最终通过直接处理字节与char的数值映射实现了正确转换,代码如下:
public long asciiToLong(char[] in) { long result = byteArrayToLong(charArrayToByteArray(in)); return result; } public char[] longToAscii(long in) { byte[] bs = longToByteArray(in); char[] result = new char[bs.length]; int i = bs.length; for (byte b : bs) { i--; result[i] = (char) b; } return result; } private long byteArrayToLong(byte[] b) { long result = 0; for (byte value : b) { result <<= Byte.SIZE; result |= (value & 0xFF); } return result; } private byte[] charArrayToByteArray(char[] charArray) { byte[] byteArray = new byte[charArray.length]; for (int i = 0 ; i < charArray.length ; i++) { byteArray[i] = (byte) (0xFF & (int) charArray[i]); } return byteArray; } private byte[] longToByteArray(long v) { byte[] b = new byte[Long.BYTES]; int i = 0; int[] j = { 0, 8, 16, 24, 32, 40, 48, 56 }; while (i < Long.BYTES) { b[i] = (byte)(v >>> j[i]); i++; } return b; }
验证测试及结果
使用以下测试代码验证:
long l; long l2; for (l = 0 ; l < 100000 ; l++) { char[] ascii = longToAscii(l); System.out.printf("%d->", l); l2 = asciiToLong(ascii); System.out.printf("%d\n", l2); if (l != l2) { throw new RuntimeException(); } }
测试输出无错误(部分):
0 -> 0 1 -> 1 2 -> 2 3 -> 3 // 中间输出省略.. 99999 -> 99999
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

