最近做了一个用.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. 站点防火墙api,增加黑名单IP接口,增加用post,修改用put,php案例

    <?php $apiHost = "http://192.168.1.198/api2/site/index.php"; $router = "token" ...

  2. day10 文件处理指针使用 函数基本使用

    一:文件指针 强调:只有t模式下read(n),n代表字符个数,除此之外都是以字节为单位 with open('a.txt',mode='rt',encoding='utf-8') as f: #文本 ...

  3. iOS8不能通过itms-services协议下载安装app

    问题:iOS包通过itms-services协议下载app无反应   使用  itms-services://?action=download-manifest&url=[ipa下载链接] 下 ...

  4. 【pyspider】初次使用pyspider遇到的问题

    <python爬虫开发与项目实践>里最后一章介绍了pyspider的使用.然鹅..我刚开始就报错了: Exception: HTTP 599: SSL certificate proble ...

  5. rancher2 HA部署注意事项

    参考: https://rancher.com/docs/rancher/v2.x/en/installation/ha-server-install/ https://www.cnblogs.com ...

  6. ucore-lab1-练习4report

    练习四:分析bootloader加载ELF格式的OS的过程  1.bootloader如何读取硬盘扇区? (1)在练习3中实现了bootloader让CPU进入保护模式,下一步的工作就是从硬盘上加载并 ...

  7. Python __import__() 函数

     Python OS 文件/目录方法 Python 面向对象  Python __import__() 函数  Python 内置函数 描述 __import__() 函数用于动态加载类和函数 . 如 ...

  8. 最近读jdk源码一些基础的总结(有待后续深入)

    第一点:java.lang 1.Object类,hashCode()方法,equals()方法,clone()方法,toString()方法,notify()和notifyAll()方法,wait() ...

  9. RocketMq --consumer自动实现负载均衡

    这边使用一个producer和两个consumer是实现负载均衡. 看一下代码示例 package com.alibaba.rocketmq.example.message.model; import ...

  10. gitbook的学习

    gitbook安装与使用之windows下搭建gitbook平台 最近需要在GitBook中去阅读电子书 安装nodejs cnpm安装gitbook 解压书籍文件,并cd到书籍文件目录 gitboo ...