【问题标题】:Get all uncompressed bytes from a compressed file从压缩文件中获取所有未压缩的字节
【发布时间】:2014-05-21 13:56:42
【问题描述】:

我创建了一种方法,用于从压缩文件中返回所有未压缩字节。

    public static byte[] GetAllBytesFromCompressedFile(string fullPath)
    {
        const int blockSize = 10000;
        byte[] block = new byte[blockSize];
        List<byte> allBytes = new List<byte>(blockSize);

        int counter = 0;
        using (FileStream file = new FileStream(fullPath, FileMode.Open))
        {
            using (DeflateStream compress = new DeflateStream(file, CompressionMode.Decompress))
            {
                int bytesRead = 0;
                do
                {
                    bytesRead = compress.Read(block, 0, blockSize);
                    counter += bytesRead;
                    allBytes.AddRange(block);
                } while (bytesRead == blockSize);
            }
        }

        return allBytes.GetRange(0, counter).ToArray();
    }

它工作正常,但它可能会在循环中被调用数百万次。大多数文件都很小,但有些可能高达 100Mb 左右,我不想为所有小文件预分配 100Mb。所以我有几个问题:

  1. 首先,框架中是否已经有这样的方法了? 还是有更好的方法?
  2. 有没有办法获得压缩文件的未压缩大小? (这样我就不必循环获取块并且可以调用一次Read
  3. 我使用了List&lt;byte&gt;,所以我不必手动重新分配一个字节 大批。有没有更有效的追加字节的方法?

我会把我的新代码放在这里,尽管它对大多数人来说可能不是一个难题。但也许有人发现了其他可以改进的地方,比如显式设置缓冲区大小(?)

    public static byte[] GetAllBytesFromCompressedFile(string fullPath)
    {
        using (MemoryStream allBytes = new MemoryStream())
        {
            using (FileStream file = new FileStream(fullPath, FileMode.Open))
            {
                using (DeflateStream compress = new DeflateStream(file, CompressionMode.Decompress))
                {
                    compress.CopyTo(allBytes);
                }
            }

            return allBytes.ToArray();
        }
    }

【问题讨论】:

    标签: c# deflatestream


    【解决方案1】:

    首先,框架中是否已经有这样的方法了?还是有更好的方法?

    使用MemoryStream作为缓冲区,使用Stream.Copy将数据复制到一行中。

    有没有办法获取压缩文件的未压缩大小?

    不,deflate 是一种流格式。您可以猜测一些值,因为未压缩的数据可能会比压缩的输入大。这样做可能是浪费时间。

    我使用了 List,因此我不必手动重新分配字节数组。有没有更有效的追加字节的方法?

    这是非常低效的。 List 类将枚举您传入的字节数组,并将字节一一相加。在一个大文件上疯狂地烧 CPU。使用MemoryStream。它使用memcpy 执行其复制操作。

    此外,您还有一个错误:您没有使用 Read 的返回值来确定读取了多少字节。您总是附加一个完整的缓冲区。建议的算法就可以解决这个问题。

    【讨论】:

    • 感谢您的回答,特别是有关使用 List 的详细信息。并指出错误:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 1970-01-01
    • 2013-11-16
    相关资源
    最近更新 更多