使用GZipStream压缩和解压文件

最近做了一个用.NET里的GZipStream压缩解压缩gzip文件的小程序。
GZipStream在System.IO.Compression底下,使用起来也很简单。虽然GZipStream是Stream类的一个下级类,但它只相当于一个转换器。在两个Stream之间将数据转换成为压缩或解压缩数据。
下面是一个简单的例子:
static void Main(string[] args)
{
    string inputFileName = @"TestFile/Test.doc";
    string outputFileName = @"TestFile/Test.doc.gz";

    // 输入输出数据流
    FileStream inputStream =
        new FileStream(inputFileName, FileMode.Open, FileAccess.Read);
    FileStream outputStream =
        new FileStream(outputFileName, FileMode.Create, FileAccess.Write);
    // 把数据读到一个字节类型的数组里
    byte[] buffer = new byte[inputStream.Length];
    inputStream.Read(buffer, 0, buffer.Length);

    GZipStream compressionStream =
        new GZipStream(outputStream, CompressionMode.Compress);

    // 把数组里的数据通过GZipStream写入到输出数据流
    compressionStream.Write(buffer, 0, buffer.Length);
    compressionStream.Close();

    inputStream.Close();
    outputFileName.Close();
    Console.WriteLine("Finished");
    Console.ReadLine();
}
以上这个例子已经可以满足基本的压缩需求,但他还有一个很大的缺点,那就是必须把全部文件都读到内存里(也就是那个字节型的数组),然后才能进行压缩。当压缩很大的文件的时候系统性能会受到很大的影响,甚至可能使系统崩溃。
所以我给他改进了一下,让他一次只读取和压缩文件的一部份:
static void Main(string[] args)
{
    string inputFileName = @"TestFile/Test.doc";
    string outputFileName = @"TestFile/Test.doc.gz";

    FileStream inputStream =
        new FileStream(inputFileName, FileMode.Open, FileAccess.Read);
    FileStream outputStream =
        new FileStream(outputFileName, FileMode.Create, FileAccess.Write);
    // 决定一次读取数剧的大小,这里是8KB
    int bufferSize = 8192;
    int bytesRead = 0;
    byte[] buffer = new byte[bufferSize];
    GZipStream compressionStream =
        new GZipStream(outputStream, CompressionMode.Compress);
    // bytesRead返回每次读了多少数据,如果等于0就表示已经没有数据
    // 可以读了
    while ( (bytesRead = inputStream.Read(buffer, 0, bufferSize)) > 0)
    {
        // 把读到数组中的数据通过GZipStream写入到输出数据流
        compressionStream.Write(buffer, 0, bytesRead);
    }
    compressionStream.Close();

    inputStream.Close();
    outputStream.Close();
    Console.WriteLine("Finished");
    Console.ReadLine();
}
好子,现在可以解决刚才提到的性能问题了。
解压缩文件和压缩文件基本一样,只不过这次GZipStream是要从已经压缩了文件中读取数据并解压缩,然后把解压后的数据写入到另一个文件,所以这次GZipStream是在读,看一面的例子:
static void Main(string[] args)
{
    string inputFileName = @"TestFile/Test.doc.gz";
    string outputFileName = @"TestFile/Test_unzipped.doc";

    FileStream inputStream =
        new FileStream(inputFileName, FileMode.Open, FileAccess.Read);
    FileStream outputStream =
        new FileStream(outputFileName, FileMode.Create, FileAccess.Write);

    int bufferSize = 8192;
    int bytesRead = 0;
    byte[] buffer = new byte[bufferSize];
    GZipStream decompressionStream =
        new GZipStream(inputStream, CompressionMode.Decompress);
    // 把压缩了的数据通过GZipStream解压缩后再读出来
    // 读出来的数据就存在数组里
    while ( (bytesRead = decompressionStream.Read(buffer, 0, bufferSize)) > 0)
    {
        // 把解压后的数据写入到输出数据流
        outputStream.Write(buffer, 0, bytesRead);
    }
    decompressionStream.Close();

    inputStream.Close();
    outputStream.Close();
    Console.WriteLine("Finished");
    Console.ReadLine();
}
我把刚才写的程序优化了一下,制作了一个比较容易使用的GZip工具 -- GZipTool,下面是这个工具支持的几个方法:
// 压缩指定文件,跟踪压缩进度,设置缓冲大小
GZipTool.Compress(string inputFileName, ProgressHandler handler, int bufferSize);
示例:
static void Main(string[] args)
{
    string inputFileName = @"TestFile/Test.doc";

    // 压缩指定文件,显示进度,并设定一次压缩数据的大小
    GZipTool.Compress(inputFileName,
        new GZipTool.ProgressHandler(_progress), 20480);
    Console.WriteLine("Finished");
    Console.ReadLine();
}
// 显示进度数据
private static void _progress(long totalBytesProcessed, long totalBytes)
{
    Console.WriteLine(
        (
        (double)totalBytesProcessed / (double) totalBytes).ToString("P")        );
}
GZipTool还支持把数据直接压缩成为数据流,可以在网络传输等不需要文件系统的环境下使用。
// 把输入数据流压缩,并把压缩后的数据包在一个MemoryStream里返回
MemoryStream GZipTool.Compress(Stream inputStream)
GZipTool在解压缩文件的时候也支持进度跟踪
// 解压指定文件并给以指定名称,跟踪压缩进度,设置缓冲大小
GZipTool.Decompress(string gZipFileName,     string outputFileName,
            ProgressHandler handler, int bufferSize)
GZipTool还支持读取gzip文件的描述信息,包括原始文件大小等
// 把指定gzip文件的描述信息读到一个GZipFileInfo结构里
GZipFileInfo GZipTool.GetFileInfo(string gZipFileName)
示例:
static void Main(string[] args)
{
    string inputFileName = @"TestFile/Test.doc.gz";

    GZipFileInfo fileInfo = GZipTool.GetFileInfo(inputFileName);
    Console.WriteLine("GZip File Name: {0}", inputFileName);
    // 输出原始文件大小
    Console.WriteLine("Original File Size: {0}", fileInfo.OriginalFileSize);
    Console.WriteLine("Finished");
    Console.ReadLine();
}
时间: 2024-08-01 04:39:16

使用GZipStream压缩和解压文件的相关文章

Linux tar(用来压缩和解压文件)

通过SSH访问服务器,难免会要用到压缩,解压缩,打包,解包等,这时候tar命令就是是必不可少的一个功能强大的工具.linux中最流行的tar是麻雀虽小,五脏俱全,功能强大. tar命令可以为linux的文件和目录创建档案.利用tar,可以为某一特定文件创建档案(备份文件),也可以在档案中改变文件,或者向档案中加入新的文件.tar最初被用来在磁带上创建档案,现在,用户可以在任何设备上创建档案.利用tar命令,可以把一大堆的文件和目录全部打包成一个文件,这对于备份文件或将几个文件组合成为一个文件以便

【转】Java压缩和解压文件工具类ZipUtil

特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/mao2080/ 1 package com.utility.zip; 2 3 import java.io.BufferedInputStream; 4 import java.io.BufferedOutputStream; 5 import java.io.File; 6 import jav

Android_JarZip压缩和解压文件

本文资料来自<android开发权威指南> AndroidSDK中提供了java.util.jar和java.util.zip包中的若干类和接口来完成. 压缩文件基本步骤: 1.创建一个JarOutputStream或ZipOutputStream对象,分别用来生成jar或zip文件. 2.创建了(jar|zip)OutputStream对象,还不能直接向输出流写入数据.由于压缩文件也需要使用文件名和路径来标识被压缩的文 件,因此,需要为每一个要压缩的文件创建一个JarEntry或ZipEnt

C# 压缩和解压文件(SharpZipLib)

先从网上下载ICSharpCode.SharpZipLib.dll类库 将文件或文件夹压缩为zip,函数如下 1 /// <summary> 2 /// 压缩文件 3 /// </summary> 4 /// <param name="fileName">压缩文件路径</param> 5 /// <param name="zipName">压缩的文件名称</param> 6 /// <pa

压缩和解压文件:tar gzip bzip2 compress(转载)

tar[必要参数][选择参数][文件] 压缩:tar -czvf filename.tar.gz targetfile解压:tar -zxvf filename.tar.gz参数说明: -c 建立新的压缩文件 -z 支持gzip解压文件 -x 从压缩的文件中提取文件 -v 显示操作过程 -f 指定压缩文件 -t 显示压缩文件的内容 gzip[必要参数][选择参数][文件或者目录] 压缩: gzip filename/*   (*号表示当前目录中的所有文件/目录分别进行压缩)解压: gzip -d

linux 压缩和解压文件(.gz\.bz2)

gzip 压缩指定文件(.gz) gzip test -c[可选参数] 压缩到指定的文件 gzip -c test > test.gz -r[可选参数] 递归压缩文件 gzip -r /usr/test 压缩目录下的所有文件 gzip /tmp/* gzip 解压指定文件(.gz) gzip -d test.gz 解压目录下的所有文件 gzip -d /usr/test/* gunzip 解压指定文件(.gz) gunzip test.gz bzip2 压缩指定文件(.bz2) bzip2 te

C#对文件操作(基本的读写以及压缩和解压)

主要是针对单个文件进行读写操作和压缩操作:用到的主要C#类有FileStream.FileInfo.StreamWrite.StreamRead.GZipStream. 字符数组和字节数组的转换: 1 byte[] bytedata = new byte[200]; 2 char[] chardata = new char[200]; 3 try 4 { 5 FileStream fs = new FileStream("App.config", FileMode.Open); 6 f

GzipStream的简单使用压缩和解压

压缩和解压都需要用到三个流实例,分别是文件读取流.文件写入流.压缩流. 读取流和写入流有多种形式,压缩流就一种GzipStream. 不同的是对于压缩,是需要用文件写入流作为创建压缩流实例的参数, 压缩时是通过文件读取流读取文件,压缩流写入文件,这样就完成了压缩. 解压,是需要用文件读取流为参数创建压缩流实例, 通过压缩读取流读取文件,再通过文件写入流写入文件,这样就完成了解压. 这里解析一个枚举CompressionMode,它有两个值分别是Compress.DeCompress. 表示压缩和

c#自带类实现的多文件压缩和解压

c#自带的System.IO.Compression命名空间下的压缩类实现的多文件压缩和解压功能,缺点是多文件压缩包的解压只能调用自身的解压方法,和现有的压缩软件不兼容.下面的代码没有把多文件的目录结构加进去 using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; namespace Test.Zip { class CompressHelper { /// <su