Java中int转ASCII再转回int异常:数值转换结果不符排查
问题分析与修复方案
我来帮你拆解一下为什么转换回去会出现数值错误,以及怎么解决这个问题!
核心问题根源
你现在的代码是用字符串来承载二进制字节数据,这本身就犯了一个逻辑错误:字符串是用来存储文本字符的,不是用来存二进制字节的。当你把像0x00(空字符)、0xE1(对应Unicode的Á)这类非标准文本字符写入文件,再用文本读取方法readLine()读取时,很容易因为编码解析、不可打印字符处理等问题导致字节被篡改——比如你遇到的65533就是Unicode的替换字符�,说明某个字节被错误解码了。
具体到你的代码,还有两个关键问题:
RandomAccessFile.writeBytes(String)会把每个char的低8位写入文件,但如果这些char是不可打印的控制字符(比如(char)0、(char)16),后续读取时可能被截断或替换。raf.readLine()是专门读取文本行的方法,它会在遇到换行符时停止读取,还会把无法解析为文本的字节替换成�(值65533),完全不适合读取二进制数据。
修复方案:直接用字节数组处理二进制数据
放弃字符串中转的思路,直接把整数转换成字节数组写入文件,读取时直接读字节数组再转回整数,彻底避开编码问题。
修改后的完整代码如下:
import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; public class IntFileHandler { public static void main(String[] args) throws IOException { File f = new File("data.txt"); RandomAccessFile raf = new RandomAccessFile(f, "rw"); // 将4321转成字节数组写入(自动判断需要3字节) raf.write(toByteArray(4321)); raf.seek(0); // 读取对应长度的字节数组并转回int // 这里因为我们知道是3字节,所以创建3字节的缓冲区;如果是自动判断,需要先存字节长度 byte[] buffer = new byte[3]; raf.read(buffer); System.out.println(fromByteArray(buffer)); // 输出4321,符合预期 raf.close(); } // 自动判断需要的字节数,将int转成字节数组(保持高位在前的顺序,和你原逻辑一致) private static byte[] toByteArray(int i) { if (i < 256) { return new byte[]{(byte) i}; } else if (i < 65536) { return new byte[]{(byte) (i >> 8), (byte) i}; } else if (i < 16777216) { return new byte[]{(byte) (i >> 16), (byte) (i >> 8), (byte) i}; } else { throw new IllegalArgumentException("数值必须小于16777216"); } } // 将字节数组转回int(处理byte的有符号问题,转成无符号值计算) private static int fromByteArray(byte[] bytes) { int result = 0; for (byte b : bytes) { // byte是有符号类型,&0xFF转成无符号的int值 result = (result << 8) | (b & 0xFF); } return result; } }
额外说明
如果你还是想保留手动指定字节数的逻辑,可以把toByteArray改成你原代码的逻辑:
private static byte[] toByteArray(int i, int b) { byte[] bytes = new byte[b]; if (b == 3) { bytes[0] = (byte) (i / 65536); bytes[1] = (byte) ((i % 65536) / 256); bytes[2] = (byte) (i % 256); } else if (b == 2) { bytes[0] = (byte) (i / 256); bytes[1] = (byte) (i % 256); } else { bytes[0] = (byte) i; } return bytes; }
调用时用raf.write(toByteArray(4321, 3))即可,效果是一样的。
内容的提问来源于stack exchange,提问作者Jonah M
相关产品推荐
相关产品推荐

