You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中ByteArrayOutputStream写入后ByteArrayInputStream读取大长整型值异常问题

问题分析

读取代码的核心错误在于:readUInt16()返回的是有符号int类型,当读取的16位值超过0x7FFF(即最高位为1)时,该int值会成为负数,转成long时会触发符号扩展(高48位填充1),最终在readUInt64()的位运算中破坏高位数据,导致大值读取错误。

由于无法修改读取代码,只能通过调整写入逻辑来适配读取代码的缺陷。


修复方案

思路

限制写入的每个16位块的最高位为0(取值范围0~0x7FFF),避免readUInt16()返回负数。若原始值的16位块最高位为1,则将该位的进位传递到高位块,确保读取时不会触发符号扩展。

修复后的写入代码

ByteArrayOutputStream baos;

public void writeUInt64(Long val) {
    long temp = val;
    // 拆分每个16位部分,确保最高位为0并处理进位
    int v0 = (int) (temp & 0x7FFF);
    temp >>= 16;
    if ((val & 0x8000) != 0) {
        temp += 1;
    }
    
    int v1 = (int) (temp & 0x7FFF);
    temp >>= 16;
    if ((temp & 0x8000) != 0) {
        temp += 1;
    }
    
    int v2 = (int) (temp & 0x7FFF);
    temp >>= 16;
    if ((temp & 0x8000) != 0) {
        temp += 1;
    }
    
    int v3 = (int) (temp & 0x7FFF);

    writeUInt16(v0);
    writeUInt16(v1);
    writeUInt16(v2);
    writeUInt16(v3);
}

public void writeUInt16(int num) {
    baos.write(num >> 0);
    baos.write(num >> 8);
}

说明
  1. 适用范围:此方案仅支持val ≤ 0x7FFF7FFF7FFF7FFFL(约1.8×10¹⁹)的数值,超过该范围的UInt64值无法通过此方法正确读取。
  2. 根本解决:若需支持任意UInt64值,必须修改读取代码,将每个readUInt16()的结果转为无符号16位值后再参与运算:
    public long readUInt64() throws IOException {
        return (readUInt16() & 0xFFFFL) | 
               ((readUInt16() & 0xFFFFL) << 16L) | 
               ((readUInt16() & 0xFFFFL) << 32L) | 
               ((readUInt16() & 0xFFFFL) << 48L);
    }
    

内容的提问来源于stack exchange,提问作者user20240747

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 19:50:21