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

C#:StreamReader结合Content-Length读取JSON时多字符问题求解

问题:使用StreamReader读取指定字节数的JSON时出现额外字符导致解析失败

从HTTP流接收JSON数据时,依赖Content-Length请求头读取消息体,但使用StreamReader实现的读取函数会在JSON后出现额外字符,导致JSON无法解析。

错误的StreamReader实现

string ReceiveJSON(StreamReader input, int msgSize)
{
    var buffer = new char[msgSize];
    int offset = 0;
    var toRead = msgSize;
    while (toRead > 0)
    {
        var charsRead = await input.ReadAsync(buffer, offset, toRead);
        offset += charsRead;
        toRead -= charsRead;
    }
    return new string(buffer, 0, msgSize);
}

正常的Stream实现(对比参考)

async Task<string> ReceiveJSON(Stream input, int msgSize)
{
    var buffer = new byte[msgSize];
    int offset = 0;
    while(msgSize > 0)
    {
        var readSize = await input.ReadAsync(buffer, offset, msgSize);
        offset += readSize;
        msgSize -= readSize;
    }
    return Encoding.UTF8.GetString(buffer);
}

解决方案:修改StreamReader实现以精确读取指定字节数

问题根源在于StreamReader是按字符读取的,而Content-Length指定的是字节数,UTF-8等编码中单个字符可能占用多字节,直接按字节数创建字符缓冲区会导致字节与字符的计数不匹配;同时StreamReader内部有缓冲区机制,可能会多读后续字节。

修改后的代码通过操作StreamReader的底层字节流来精确读取指定字节数,再用StreamReader的编码转换为字符串:

async Task<string> ReceiveJSON(StreamReader input, int msgSize)
{
    var buffer = new byte[msgSize];
    int offset = 0;
    int remainingBytes = msgSize;

    while (remainingBytes > 0)
    {
        var bytesRead = await input.BaseStream.ReadAsync(buffer, offset, remainingBytes);
        if (bytesRead == 0)
            throw new IOException("数据流提前结束,未读取到指定字节数");
        
        offset += bytesRead;
        remainingBytes -= bytesRead;
    }

    // 使用StreamReader当前的编码转换字节,确保与HTTP响应编码一致
    return input.CurrentEncoding.GetString(buffer);
}

修改说明

  1. 直接操作StreamReader.BaseStream:底层字节流可以精确按Content-Length的字节数读取,避免StreamReader的字符读取逻辑干扰。
  2. 使用input.CurrentEncoding:避免硬编码UTF-8,确保和StreamReader根据HTTP响应头自动识别的编码一致(比如GBK、UTF-16等)。
  3. 保留循环读取逻辑:处理流分批次返回数据的情况,确保读取到完整的指定字节数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 01:39:40