C# 用GZipStream压缩

C# 用GZipStream压缩,c#,.net,C#,.net,我试图理解为什么我的代码没有按预期执行。它创建一个GZipStream,然后将对象作为压缩文件保存在我的硬盘上,但保存的文件总是0字节 现在我知道怎么做了,但我的问题不是怎么做。我的问题纯粹是为什么这段代码可以节省0字节(或者为什么FileStream可以工作而内存不能) 关于源代码,this.fileName=c:\Audio.wav,而newFileName是c:\Audio.wav.gz(但也尝试了c:\Audio.gz) 因为MemoryStream的备份存储是您的RAM内存,而不是硬盘

我试图理解为什么我的代码没有按预期执行。它创建一个GZipStream,然后将对象作为压缩文件保存在我的硬盘上,但保存的文件总是0字节

现在我知道怎么做了,但我的问题不是怎么做。我的问题纯粹是为什么这段代码可以节省0字节(或者为什么FileStream可以工作而内存不能)

关于源代码,
this.fileName=c:\Audio.wav
,而
newFileName
c:\Audio.wav.gz
(但也尝试了
c:\Audio.gz

因为MemoryStream的备份存储是您的RAM内存,而不是硬盘驱动器。因此,当您将
MemoryStream
对象传递给
GZipStream
构造函数时,gzip就在RAM中

使用此代码:

using (FileStream fs =new FileStream(this.newFileName, FileMode.CreateNew))
您正在创建新的FileStream,但未使用它。要使用此FIleStream存储gzip,您需要将其传递给
GZipStream
构造函数,使其成为硬盘驱动器的备份存储。

  • 您不需要MemoryStream,因为
    字节
    已经有了要压缩的数据
  • 不应使用ms.ReadByte()
  • 创建
    zipStream
    时,应使用输出文件流
试试这个:

var bytes = File.ReadAllBytes(this.fileName);
using (FileStream fs =new FileStream(this.newFileName, FileMode.CreateNew))
using (GZipStream zipStream = new GZipStream(fs, CompressionMode.Compress, false))
{
     zipStream.Write(bytes, 0, bytes.Length);
}
编辑


原始代码创建了一个零长度文件,因为您没有写入文件流。

当您从
System.IO.Compression
命名空间使用
gzip流
DeflateStream
时,您在构造函数中提供的
流将写入进行压缩解压中读取

由于您试图在此处压缩数据,因此使用
MemoryStream
是不正确的,因为您不是试图压缩数据,而是将其用作数据源。因此,您的
MemoryStream
应该是输入
Stream
,而
FileStream
是您的输出

我强烈建议您使用
MemoryStream
作为原始
字节[]
的数据源,因为
具有更多的通用性和应用程序(
文件流
网络流
加密流
,等等)

下面是一些使用
async
/
await
模式的示例:

public static async Task CompressToFileAsync(byte[] buffer, 
                                             string outputFile)
{
  using (var inputStream = new MemoryStream(buffer))
    await CompressToFileAsync(inputStream, outputFile);
}

public static async Task CompressToFileAsync(Stream inputStream, 
                                             string outputFile)
{
  using (var outputStream = File.Create(outputFile))
  using (var gzip = new GZipStream(outputStream, CompressionMode.Compress))
  {
    await inputStream.CopyToAsync(gzip);
    gzip.Close();
  }
}

public static async Task<MemoryStream> DecompressFromFileAsync(string inputFile)
{
  var outputStream = new MemoryStream();

  using (var inputStream = File.Open(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read))
  using (var gzip = new GZipStream(inputStream, CompressionMode.Decompress))
  {
    await gzip.CopyToAsync(outputStream);

    gzip.Close();
    inputStream.Close();

    // After writing to the MemoryStream, the position will be the size
    // of the decompressed file, we should reset it back to zero before returning.
    outputStream.Position = 0;
    return outputStream;
  }
}
公共静态异步任务CompressToFileAsync(字节[]缓冲区,
字符串输出文件)
{
使用(var inputStream=新内存流(缓冲区))
等待CompressToFileAsync(inputStream、outputFile);
}
公共静态异步任务CompressToFileAsync(Stream inputStream,
字符串输出文件)
{
使用(var outputStream=File.Create(outputFile))
使用(var gzip=new GZipStream(outputStream,CompressionMode.Compress))
{
等待inputStream.CopyToAsync(gzip);
gzip.Close();
}
}
公共静态异步任务解压缩自FileAsync(字符串输入文件)
{
var outputStream=new MemoryStream();
使用(var inputStream=File.Open(inputFile,FileMode.Open,FileAccess.Read,FileShare.Read))
使用(var gzip=new GZipStream(inputStream,CompressionMode.Decompress))
{
等待gzip.CopyToAsync(outputStream);
gzip.Close();
inputStream.Close();
//写入MemoryStream后,该位置将为大小
//对于解压缩的文件,我们应该在返回之前将其重置为零。
outputStream.Position=0;
返回输出流;
}
}

注意:在关闭输入或输出
流之前,始终调用
GzipStream.Close()
。它在关闭/释放时进行一些最终的缓冲区刷新,如果输入或输出先关闭,它将在尝试这样做时抛出异常。(这也适用于
DeflateStream

我使用此类进行压缩/解压缩:

internal class GZipProcessor : IZipProcessor
{

    public byte[] Compress(byte[] data)
    {
        using (var compressedStream = new MemoryStream())
        {
            using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress))
            {
                zipStream.Write(data, 0, data.Length);
                zipStream.Close();
                return compressedStream.ToArray();
            }
        }
    }

    public byte[] Decompress(byte[] data)
    {
        using (var compressedStream = new MemoryStream(data))
        {
            using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
            {
                using (var resultStream = new MemoryStream())
                {
                    zipStream.CopyTo(resultStream);
                    return resultStream.ToArray();
                }
            }
        }
    }

}
以及我如何使用它:

public void Compress(string inputPath, string outputPath)
{
    byte[] originalBytes = File.ReadAllBytes(inputPath);
    byte[] zippedBytes = base.ZipProcessor.Compress(originalBytes);
    File.WriteAllBytes(outputPath, zippedBytes);
}

public void Decompress(string inputPath, string outputPath)
{
    byte[] zippedBytes = File.ReadAllBytes(inputPath);
    byte[] originalBytes = base.ZipProcessor.Decompress(zippedBytes);
    File.WriteAllBytes(outputPath, originalBytes);
}

<>我还有一个更复杂的代码

你也可以考虑转换为MP3;看见
internal class GZipProcessor : IZipProcessor
{

    public byte[] Compress(byte[] data)
    {
        using (var compressedStream = new MemoryStream())
        {
            using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress))
            {
                zipStream.Write(data, 0, data.Length);
                zipStream.Close();
                return compressedStream.ToArray();
            }
        }
    }

    public byte[] Decompress(byte[] data)
    {
        using (var compressedStream = new MemoryStream(data))
        {
            using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
            {
                using (var resultStream = new MemoryStream())
                {
                    zipStream.CopyTo(resultStream);
                    return resultStream.ToArray();
                }
            }
        }
    }

}
public void Compress(string inputPath, string outputPath)
{
    byte[] originalBytes = File.ReadAllBytes(inputPath);
    byte[] zippedBytes = base.ZipProcessor.Compress(originalBytes);
    File.WriteAllBytes(outputPath, zippedBytes);
}

public void Decompress(string inputPath, string outputPath)
{
    byte[] zippedBytes = File.ReadAllBytes(inputPath);
    byte[] originalBytes = base.ZipProcessor.Decompress(zippedBytes);
    File.WriteAllBytes(outputPath, originalBytes);
}