【问题标题】:C# MemoryStream.CopyTo(fileStream) adding extra bytes and corrupting OpenXML fileC# MemoryStream.CopyTo(fileStream) 添加额外字节并损坏 OpenXML 文件
【发布时间】:2020-05-17 00:26:16
【问题描述】:

我正在使用 OpenXML 生成 Excel 电子表格。

我在 MemoryStream 中生成电子表格;调用者正在写出实际的文件。例如,我的 .Net Core 控制器会将内存流返回为 FileResult。目前,我有一个独立的控制台模式程序,它正在编写一个 FileStream。

问题:我在文件末尾得到了额外的字节。由于 OpenXml .xlsx 文件是 .zip 文件,因此额外的字节会有效地破坏文件。

Program.cs

using (MemoryStream memoryStream = new MemoryStream())
{
    OpenXMLGenerate(memoryStream, sampleData);
    long msPos = memoryStream.Position;  // Position= 1869: Good!
    memoryStream.Position = 0;
    using (FileStream fs = new FileStream("myfile.xlsx", FileMode.OpenOrCreate))
    {
        memoryStream.WriteTo(fs);
        long fsPos = fs.Position;  // Position= 1869: Good!
    }
    // Myfile.xlsx filesize= 2014, not 1869! Bad!!!
}

当我在 7-Zip 中打开文件时,它显示:

警告:payload数据结束后有一些数据

物理尺寸:1869

尾巴尺寸:145

当我尝试将其作为 .zip 文件打开时,Windows 显示:

压缩(压缩)文件夹无效。

问:知道为什么我得到的是 2014 字节的文件,而不是 1869 字节的文件吗?

问:我该怎么办?

【问题讨论】:

  • FileMode.Create而不是FileMode.OpenOrCreate创建FileStream会导致同样的问题吗?
  • 谢谢!它确实。我刚试过FileMode.Create: 效果很好。内存流、文件流...和生成的文件现在都是 1867 字节(正确!)。 不是 1869,当然不是2014。问:为什么????如果您发表回复,我很乐意支持/接受。
  • FileMode.OpenOrCreate 等效于 FileMode.Open 如果文件已经存在。该操作可能会覆盖现有文件的前 1869 个字节,而保留现有文件的其余部分不变。使用FileMode.Create 将确保旧文件(如果存在)被完全替换。

标签: c# filestream


【解决方案1】:

(按 cmets 记录。)可以通过文件替换长度为 2014 字节的现有文件来解释该问题。

如果引用的文件存在,则使用FileMode.OpenOrCreate 模式创建文件流等效于使用FileMode.Open。如果内存流的长度小于现有文件的长度,则现有文件不会被截断为内存流的长度;在这种情况下,如果 N 是内存流的长度,则现有文件的前 N ​​个字节将被内存流的内容覆盖,其余字节将从原始文件中保留。

使用FileMode.Create 文件模式创建文件流将完全替换现有文件(如果存在),消除新文件包含现有文件残余的任何可能性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-22
    相关资源
    最近更新 更多