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

WCF REST服务以Stream为输入参数时首字符丢失的解决方法

问题:WCF REST服务接收Stream时丢失首字符

我开发了一个以Stream作为输入参数的WCF REST服务,契约定义如下:

[OperationContract]
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
void ImportStream(Stream data);

实现代码为:

public void ImportStream(Stream data)
{
    if (data.ReadByte() != -1)
    {
        using (var reader = new StreamReader(data))
        {
            string textRead = reader.ReadToEnd();
        }
    }
}

我在Postman中传入的输入文本为:

D_CA,P_AMOUNT,D_AN,D_PE,D_RU,D_ORU,D_AC,,D_GO,D_LE,D_NU,D_CO,D_MU,D_PMU,D_DP,P_COMMENT
A,100,,2019.12,S000,S000,XA1810,F00,PACK01,,S002,EUR,ORIG07-01,0000.PACKAGE,,,,,,2019.12,
A,100,,2019.12,S000,S000,XA1810,F00,PACK01,,S004,EUR,ORIG07-01,0000.PACKAGE,,,,,,2019.12,

但最终读取到的textRead内容丢失了首字符'D',变为"_CA,P_AMOUNT,D_AN,D_PE,D_RU,D_ORU,D_AC,,D_GO,D_LE,D_NU,D_CO,D_MU,D_PMU,D_DP,P_COMMENT.......",请问该如何修复这个问题?


解决方案

这个问题的根源很清楚:你在判断流是否有数据时调用了data.ReadByte(),这个方法会把流的第一个字节(也就是首字符'D')读取出来并消耗掉,流的位置随即移动到第二个字节。之后StreamReader从当前位置开始读取,自然就跳过了第一个字符。

下面提供几种可行的修复方案,按推荐程度排序:

方案一:直接读取流,无需提前判断

其实StreamReader.ReadToEnd()在流为空时只会返回空字符串,完全不需要提前判断流是否有数据。这种写法最简洁,也彻底避免了流位置的问题:

public void ImportStream(Stream data)
{
    using (var reader = new StreamReader(data))
    {
        string textRead = reader.ReadToEnd();
        // 仅在文本非空时处理
        if (!string.IsNullOrWhiteSpace(textRead))
        {
            // 执行你的业务逻辑
        }
    }
}

方案二:用Peek()判断流是否有数据

如果你确实需要提前判断流是否非空,可以用Peek()方法——它只会查看流的下一个字节,不会移动流的位置,这样既完成了判断,又不会消耗首字符:

public void ImportStream(Stream data)
{
    // Peek()返回-1表示流已到末尾,否则说明有数据可读
    if (data.Peek() != -1)
    {
        using (var reader = new StreamReader(data))
        {
            string textRead = reader.ReadToEnd();
            // 处理文本
        }
    }
}

方案三:读取首字节后重置流位置(仅适用于支持查找的流)

如果一定要保留ReadByte()的判断逻辑,那在判断后需要把流的位置重置到起始处。不过要注意,这种方式只适用于支持查找操作的流(比如MemoryStream),如果是网络流这类不支持查找的流,访问Position属性会抛出异常:

public void ImportStream(Stream data)
{
    int firstByte = data.ReadByte();
    if (firstByte != -1)
    {
        // 将流位置重置到开头
        data.Position = 0;
        using (var reader = new StreamReader(data))
        {
            string textRead = reader.ReadToEnd();
            // 处理文本
        }
    }
}

综合来看,方案一是最优选择,既简洁又没有潜在的兼容性问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 08:02:48