最近做了一个用.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, , buffer.Length); GZipStream compressionStream =
new GZipStream(outputStream, CompressionMode.Compress); // 把数组里的数据通过GZipStream写入到输出数据流
compressionStream.Write(buffer, , 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 = ;
int bytesRead = ;
byte[] buffer = new byte[bufferSize];
GZipStream compressionStream =
new GZipStream(outputStream, CompressionMode.Compress);
// bytesRead返回每次读了多少数据,如果等于0就表示已经没有数据
// 可以读了
while ( (bytesRead = inputStream.Read(buffer, , bufferSize)) > )
{
// 把读到数组中的数据通过GZipStream写入到输出数据流
compressionStream.Write(buffer, , 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 = ;
int bytesRead = ;
byte[] buffer = new byte[bufferSize];
GZipStream decompressionStream =
new GZipStream(inputStream, CompressionMode.Decompress);
// 把压缩了的数据通过GZipStream解压缩后再读出来
// 读出来的数据就存在数组里
while ( (bytesRead = decompressionStream.Read(buffer, , bufferSize)) > )
{
// 把解压后的数据写入到输出数据流
outputStream.Write(buffer, , 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), );
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();
}

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

  1. C#压缩和解压文件

    这里用两种方法实现C#压缩和解压文件 1.使用System.IO.Compression名称空间下的相关类(需引用 System.IO.Compression.FileSystem和System.IO ...

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

    特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...

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

    tar[必要参数][选择参数][文件] 压缩:tar -czvf filename.tar.gz targetfile解压:tar -zxvf filename.tar.gz参数说明: -c 建立新的 ...

  4. linux 压缩和解压文件

    一.压缩:20120715文件下面所有的文件 如下: tar -zcvf 20120715.tar.gz  20120715* 二.解压20120715.tar.gz压缩包 如下: tar -xzvf ...

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

    先从网上下载ICSharpCode.SharpZipLib.dll类库 将文件或文件夹压缩为zip,函数如下 /// <summary> /// 压缩文件 /// </summary ...

  6. c#调用WinRAR软件压缩和解压文件

    using System; using System.Collections.Generic; using System.Web; using System.IO; using System.Linq ...

  7. linux压缩和解压文件命令

    tar  解包:tar zxvf filename.tar  打包:tar czvf filename.tar dirnamegz命令  解压1:gunzip filename.gz  解压2:gzi ...

  8. GZipStream 压缩和解压

    GZipSteam: GZip 数据格式,它使用无损压缩和解压缩文件的行业标准算法 类 GZipStream有两种模式:CompressionMode.Compress和CompressionMode ...

  9. Android_JarZip压缩和解压文件

        本文资料来自<android开发权威指南> AndroidSDK中提供了java.util.jar和java.util.zip包中的若干类和接口来完成. 压缩文件基本步骤: 1.创 ...

随机推荐

  1. AssetBundle Manager

    [AssetBundle Manager] AssetBundleManager是一个款Unity公司制作的Unity库. 1.Simulation Mode The main advantage o ...

  2. 初探Mybaties整合分页插件PageHelper(1)

    Mybaites整合分页PageHelper插件 在数据进行分页,通过sql语句,mysql分页,table_name表名,pageNum 第几页,pageSize 每页数据条数: SELECT * ...

  3. WeakHashMap<K,V> 中的弱引用

    相信很多人对WeakHashMap并没有完全理解. WeakHashMap 持有的弱引用的 Key. 1. 弱引用的概念: 弱引用是用来描述非必需对象的,被弱引用关联的对象只能生存到下一次垃圾收集发生 ...

  4. mysql创建用户和库

    先用root登陆mysql,然后运行下面代码创建mysql用户和库 下面创建的帐号:test123  密码:123456  库名:test123 CREATE USER '; GRANT USAGE ...

  5. centos 6.9 NTP基准时间服务器配置

    时间服务器端 yum install ntp -y vim /etc/ntp.conf 增加允许客户端访问 restrict 192.168.0.0 mask 255.255.0.0 nomodify ...

  6. Ubuntu 14.04 LTS 安装Docker(转)

    转自:https://www.cnblogs.com/leolztang/p/5097278.html Docker官方是有很详细的安装文档(https://docs.docker.com/engin ...

  7. javascript简单的滑动效果

    利用setInterval实现简单的滑动效果 <!DOCTYPE html> <html lang="en"> <head> <meta ...

  8. 【svn】服务器搭建和迁移

    导语 svn客户端大部分开发都会用到,但是为什么我们仍然需要svn服务端呢? 理由可能有: 1,我们想存放一些属于自己的文档,而不像被其他人发现(在自己的网络环境中,安全性更高,更易用,不依赖于公司, ...

  9. [HDOJ]Coin Change(DP)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2069 题意 有面值1,5,10,25,50的硬币数枚,对于输入的面值n,输出可凑成面值n(且限制总硬笔 ...

  10. js文字展示各种滚动效果

    js文字展示各种滚动效果:http://www.dowebok.com/demo/188/