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); }
修改说明
- 直接操作
StreamReader.BaseStream:底层字节流可以精确按Content-Length的字节数读取,避免StreamReader的字符读取逻辑干扰。 - 使用
input.CurrentEncoding:避免硬编码UTF-8,确保和StreamReader根据HTTP响应头自动识别的编码一致(比如GBK、UTF-16等)。 - 保留循环读取逻辑:处理流分批次返回数据的情况,确保读取到完整的指定字节数。
内容的提问来源于stack exchange,提问作者pf12345678910
相关产品推荐
相关产品推荐

