【问题标题】:Compression stream appears empty压缩流显示为空
【发布时间】:2012-04-27 18:23:30
【问题描述】:

我需要使用 GZip 按指定大小(不是整体)压缩文件。我可以成功填充 byte[] 缓冲区,但是在将其复制到压缩流后,它只是将输出流留空。

public void Compress(string source, string output)
    {
        FileInfo fi = new FileInfo(source);
        byte[] buffer = new byte[BufferSize];
        int total, current = 0;
        using (FileStream inFile = fi.OpenRead())
        {
            using (FileStream outFile = File.Create(output + ".gz"))
            {
                while ((total = inFile.Read(buffer, 0, buffer.Length)) != 0)
                {
                    using (MemoryStream compressedStream = new MemoryStream())
                    {
                        using (MemoryStream bufferStream = new MemoryStream())
                        {
                            CopyToStream(buffer, bufferStream);
                            using (GZipStream Compress = new GZipStream(compressedStream, CompressionMode.Compress, true))
                            {
                                bufferStream.Position = 0;
                                bufferStream.CopyTo(Compress);
                                current += total;
                            }
                            compressedStream.Position = 0;
                            compressedStream.CopyTo(outFile);
                        }
                    }
                }
            }
        }
    }

    static void CopyToStream(byte[] buffer, Stream output)
    {
        output.Write(buffer, 0, buffer.Length);
    }

【问题讨论】:

    标签: c# gzip memorystream gzipstream


    【解决方案1】:

    您需要通过在compressedStream.CopyTo(outFile); 之前设置Position=0 来回退compressedStream。

    【讨论】:

    • 请注意,我的答案是针对您的确切问题,但您可能只是一次压缩块而做错了。我认为 .gz 应该是带有一个压缩字典的单个压缩块。您的代码可能会创建普通解压缩器无法读取的文件。
    • 你会怎么做?批处理的原因是进度监控。我想我会在每批完成后触发一个事件。我不认为我可以触摸压缩流本身,所以我是这样设计的。
    • 看做没有问题。为什么需要在每 x 个字节写入流后提交每个块以触发事件?
    • 不确定我是否正确理解了这个问题,但我会尽力回答。我需要在处理每个批次后触发一个事件,因为我在说明中有它(不是我的想法)。我认为它的目的是推动进度条或类似的东西。
    • 我不知道你需要做什么,所以让我们认为它已解决。 (对于事件,我的意思是在 bufferStream.CopyTo(Compress) 周围被触发并将 Compress 流移到 while 循环之外)
    【解决方案2】:

    您试图使事情变得过于复杂...您不需要额外的 MemoryStreams 或缓冲区...

    取自 MSDN...http://msdn.microsoft.com/en-us/library/system.io.compression.gzipstream.aspx

    public static void Compress(FileInfo fi)
        {
            // Get the stream of the source file.
            using (FileStream inFile = fi.OpenRead())
            {
                // Prevent compressing hidden and 
                // already compressed files.
                if ((File.GetAttributes(fi.FullName) 
                    & FileAttributes.Hidden)
                    != FileAttributes.Hidden & fi.Extension != ".gz")
                {
                    // Create the compressed file.
                    using (FileStream outFile = 
                                File.Create(fi.FullName + ".gz"))
                    {
                        using (GZipStream Compress = 
                            new GZipStream(outFile, 
                            CompressionMode.Compress))
                        {
                            // Copy the source file into 
                            // the compression stream.
                        inFile.CopyTo(Compress);
    
                            Console.WriteLine("Compressed {0} from {1} to {2} bytes.",
                                fi.Name, fi.Length.ToString(), outFile.Length.ToString());
                        }
                    }
                }
            }
        }
    

    【讨论】:

    • 谢谢,但我确实需要分批做,这样我才能监控进度。
    猜你喜欢
    • 1970-01-01
    • 2014-03-31
    • 1970-01-01
    • 2021-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-19
    • 2013-09-21
    相关资源
    最近更新 更多