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

Java中如何解析普通字符串与GZIP压缩字符串混合的Socket数据?

解析混合普通字符串与压缩XML的Socket数据包

现有代码的核心问题

  1. 数据读取不完整:InputStream.read(byte[])仅能读取部分数据,无法保证一次性获取完整数据包;后续的Arrays.copyOfRange(bytes,0,1025)还存在数组越界问题(原数组长度为1024,索引最大值为1023)。
  2. 解压输入错误:你提取了endbytes作为压缩数据,但实际解压时传入的是包含头部8字节和普通字符串的原始bytes数组——GZIPInputStream只能处理纯压缩字节流,混入无关数据必然导致解压乱码。
  3. 未明确数据拆分规则:头部8字节的具体定义(比如是否包含总长度、普通字符串长度)不明确,导致无法正确拆分普通字符串与压缩XML部分。

正确解析步骤

1. 读取完整的头部与数据包

头部固定8字节,通常会包含数据包总长度。先读取头部并解析总长度,再循环读取剩余字节以确保获取完整数据:

Socket socket = serverSocket.accept();
InputStream is = socket.getInputStream();

// 读取头部8字节
byte[] header = new byte[8];
int readLen = is.read(header);
if (readLen != 8) {
    throw new IOException("Failed to read complete header");
}

// 解析头部中的总长度(假设头部前4字节为大端序总长度,需根据实际协议调整)
int totalLength = ByteBuffer.wrap(header, 0, 4).getInt();
int contentLength = totalLength - 8; // 剩余内容长度 = 总长度 - 头部长度

// 读取完整内容
byte[] content = new byte[contentLength];
int offset = 0;
while (offset < contentLength) {
    int bytesRead = is.read(content, offset, contentLength - offset);
    if (bytesRead == -1) {
        throw new IOException("Connection closed before reading complete content");
    }
    offset += bytesRead;
}

2. 拆分普通字符串与压缩XML部分

假设协议定义:头部后4字节为普通字符串的长度(需根据实际协议调整,比如普通字符串以特定分隔符结尾),先提取普通字符串,再提取压缩XML字节流:

// 解析普通字符串长度(假设头部后4字节为大端序长度)
int plainStrLength = ByteBuffer.wrap(header, 4, 4).getInt();

// 提取普通字符串(编码需与服务器一致,示例用UTF-8)
String plainStr = new String(content, 0, plainStrLength, StandardCharsets.UTF_8);

// 提取压缩XML的纯字节数组
byte[] compressedXmlBytes = Arrays.copyOfRange(content, plainStrLength, content.length);

3. 正确解压压缩XML部分

使用提取后的纯压缩字节流进行GZIP解压,注意XML的编码需与服务器输出一致:

String xmlContent;
try (ByteArrayInputStream bais = new ByteArrayInputStream(compressedXmlBytes);
     GZIPInputStream gzipIn = new GZIPInputStream(bais);
     ByteArrayOutputStream baos = new ByteArrayOutputStream()) {

    byte[] buffer = new byte[1024];
    int n;
    while ((n = gzipIn.read(buffer)) != -1) {
        baos.write(buffer, 0, n);
    }
    // XML通常用UTF-8编码,需和服务器保持一致
    xmlContent = baos.toString(StandardCharsets.UTF_8.name());
} catch (IOException e) {
    throw new RuntimeException("Failed to decompress XML data", e);
}

// 输出解析结果
System.out.println("Plain string: " + plainStr);
System.out.println("Decompressed XML: " + xmlContent);

关键注意事项

  • 明确协议细节:必须确认头部8字节的具体含义、普通字符串与压缩数据的拆分规则,这是解析的核心前提,若不明确需与服务端对接确认。
  • 编码一致性:普通字符串和XML的编码必须与服务器端使用的编码完全一致,避免字符乱码。
  • 流资源管理:使用try-with-resources自动关闭流,防止资源泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 09:20:34