在查找并压缩文件后,在最后一行获得额外的空间

时间:2018-08-08 15:01:50

标签: c#

使用下面的代码,我正在使用文件查找并将结果字节转换为压缩流并生成zip文件,

public static async Task Get(string filename)
{
    byte[] result;
    byte[] compressedBytes;

    using (FileStream SourceStream = File.Open(filename, FileMode.Open))
    {
        SourceStream.Seek(20, SeekOrigin.Begin);

        result = new byte[SourceStream.Length];

        await SourceStream.ReadAsync(result, 0, (int)SourceStream.Length);
    }


    string fileName = "Export_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".zip";

    using (var outStream = File.Create(fileName))
    {
        using (var archive = new ZipArchive(outStream, ZipArchiveMode.Create, true))
        {
            var fileInArchive = archive.CreateEntry("test.txt", CompressionLevel.Optimal);
            using (var entryStream = fileInArchive.Open())
            using (var fileToCompressStream = new MemoryStream(result))
            {
                fileToCompressStream.CopyTo(entryStream);
            }
        }
    }
}

现在,当我解压缩生成的文件时,将具有额外的空间。是什么原因以及如何解决?

enter image description here

1 个答案:

答案 0 :(得分:2)

您要在流中寻找20个字节,但是数组的长度是流的完整长度。因此,您数组中的最后20个字节将被忽略。

对此的简单解决方法是分配更少的空间,然后仅要求读取减少的字节数:

result = new byte[SourceStream.Length - 20];
await SourceStream.ReadAsync(result, 0, result.Length);

请注意,您还假设一次调用ReadAsync将读取所有数据。在很多情况下都可能是这种情况,但是通常不建议将其视为流。

不过,将文件直接从文件流直接复制到压缩流会更简单,而不是先将整个文件读入内存中。

public static async Task Get(string filename)
{
    string outputFile = "Export_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".zip";

    using (var outStream = File.Create(outputFile))
    {
        using (var archive = new ZipArchive(outStream, ZipArchiveMode.Create, true))
        {
            var fileInArchive = archive.CreateEntry("test.txt", CompressionLevel.Optimal);
            using (var entryStream = fileInArchive.Open())
            using (var fileToCompressStream = File.Open(filename, FileMode.Open))
            {
                // Skip the first 20 bytes
                fileToCompressStream.Position = 20;
                fileToCompressStream.CopyTo(entryStream);
            }
        }
    }
}