为什么此副本Stream比其原始Stream更大?

时间:2017-04-25 22:28:49

标签: c# .net memory stream

我试图修改文件流,但我遇到了一些有趣的事情。当我从原始流中读取一个字符串然后尝试将其写入一个新流时,我最终会得到比原始流更大的字符串。

我没有发现任何类似的问题。有人可以澄清发生了什么吗?我介入并注意到变量的大小

private Stream CopyAndChangeStreamContents(Stream input)
{
    input.Position = 0; //input.Length is (long)84863 

    string contents = new StreamReader(input).ReadToEnd(); //contents.Length is (int)80765 

    Stream output = new MemoryStream();
    new StreamWriter(output).Write(contents); //output.Length is (long)151950 

    output.Flush();
    return output;
}

编辑#2 Downvoter:该方法的评论和意图并不能解释这里发生的事情。无论正在读取什么类型的数据,我想了解底层流功能导致如此剧烈的大小差异

当读取字节时,如果它来自zip或文本文件无关紧要,字节仍然是字节,所以如果我有一个输入0110 0001 0110 0010 0110 0011 0110 0100,我希望仍然可以读取4个字节。即使我把它读作字符串' abcd',如果我完全按照我发现的那样写回二进制文件,它也不会对我有所影响。

为什么一个Stream给我的长度为84863,而另一个流给我的长度为151950?

修改: 我尝试使用StreamReader构造函数来尝试读取编码:

var reader = new StreamReader(input, true);

以后写出时使用相同的编码:

new StreamWriter(output, reader.CurrentEncoding).Write(contents);

..无济于事。同样的问题。

1 个答案:

答案 0 :(得分:2)

您的信息流包含非UTF-8的二进制数据。 StreamReader(Stream)的默认构造函数使用UTF-8解码器,用Unicode replacement characterU+FFFD替换无法识别的字节序列。

假设输入流包含五个字节41 80 81 82 7A。然后new StreamReader(input).ReadToEnd()返回字符串"A���z",因为0x80(以及0x810x82)无法解码为C#char使用UTF-8编码。

调用new StreamWriter(output).Write()将该字符串编码为UTF-8并将其写入输出流。 U+FFFD以UTF-8编码为三字节序列EF BF BD。所以在这个例子中,它会写出11个字节:41 EF BF BD EF BF BD EF BF BD 7A

将无法识别的字节转换为�到EF BF BD解释了为什么当您阅读然后编写它时,您的流的大小会增大。

解决方案是读取和写入byte[],而不是将任意二进制数据转换为string