为什么这个副本 Stream 比它的原始 Stream 大?

Fel*_*ipe 3 .net c# 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;
}
Run Code Online (Sandbox Code Playgroud)

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

读取字节时,无论它来自 zip 文件还是文本文件都没有关系,字节仍然是字节,因此如果我有输入,0110 0001 0110 0010 0110 0011 0110 0100我希望仍然读取 4 个字节。即使我将其读为字符串 'abcd',如果我完全按照我找到的方式写回二进制文件,对我来说也不会有什么不同。

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

编辑:我尝试使用 StreamReader 构造函数尝试读取编码:

var reader = new StreamReader(input, true);

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

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

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

Bra*_*ger 6

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

让我们假设输入流包含五个字节41 80 81 82 7A。然后new StreamReader(input).ReadToEnd()返回 string "A???z",因为0x80(and0x810x82) 不能char使用 UTF-8 编码解码为 C# 。

调用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.