使用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, , 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压缩和解压文件的更多相关文章
- C#压缩和解压文件
这里用两种方法实现C#压缩和解压文件 1.使用System.IO.Compression名称空间下的相关类(需引用 System.IO.Compression.FileSystem和System.IO ...
- 【转】Java压缩和解压文件工具类ZipUtil
特别提示:本人博客部分有参考网络其他博客,但均是本人亲手编写过并验证通过.如发现博客有错误,请及时提出以免误导其他人,谢谢!欢迎转载,但记得标明文章出处:http://www.cnblogs.com/ ...
- 压缩和解压文件:tar gzip bzip2 compress(转)
tar[必要参数][选择参数][文件] 压缩:tar -czvf filename.tar.gz targetfile解压:tar -zxvf filename.tar.gz参数说明: -c 建立新的 ...
- linux 压缩和解压文件
一.压缩:20120715文件下面所有的文件 如下: tar -zcvf 20120715.tar.gz 20120715* 二.解压20120715.tar.gz压缩包 如下: tar -xzvf ...
- C# 压缩和解压文件(SharpZipLib)
先从网上下载ICSharpCode.SharpZipLib.dll类库 将文件或文件夹压缩为zip,函数如下 /// <summary> /// 压缩文件 /// </summary ...
- c#调用WinRAR软件压缩和解压文件
using System; using System.Collections.Generic; using System.Web; using System.IO; using System.Linq ...
- linux压缩和解压文件命令
tar 解包:tar zxvf filename.tar 打包:tar czvf filename.tar dirnamegz命令 解压1:gunzip filename.gz 解压2:gzi ...
- GZipStream 压缩和解压
GZipSteam: GZip 数据格式,它使用无损压缩和解压缩文件的行业标准算法 类 GZipStream有两种模式:CompressionMode.Compress和CompressionMode ...
- Android_JarZip压缩和解压文件
本文资料来自<android开发权威指南> AndroidSDK中提供了java.util.jar和java.util.zip包中的若干类和接口来完成. 压缩文件基本步骤: 1.创 ...
随机推荐
- Python调用sqlAlchemy
import logging from sqlalchemy import Column, String, create_engine from sqlalchemy.ext.declarative ...
- OnContextMenu实现禁止鼠标右键
OnContextMenu事件 定义和使用:oncontextmenu 事件在元素中用户右击鼠标时触发并打开上下文菜单.注意:所有浏览器都支持 oncontextmenu 事件, contextmen ...
- 解决在linux环境安装setuptools的相关错误
RuntimeError: Compression requires the (missing) zlib module 缺少zlib包 解决方案 yum install zlib yum i ...
- Pandas汇总和处理缺失数据
汇总的函数 方法 说明 count 非NA的值数量 describe 针对Series和DataFrame列计算汇总统计 min.max 计算最小值和最大值 argmin.argmax 计算能够获取到 ...
- 对象转化为json
google开发的Gson转换利器,String json = new Gson ().toJson(object); 一行代搞定. 别忘了引入jar包 转自:https://zhidao.baidu ...
- C#中与C++中的 LPWSTR(wchar_t *) 对应的类型
1.设置 CharSet = CharSet.Unicode [DllImport("test.dll", EntryPoint = "sum()", Char ...
- leetcode 中等题(1)
2. Add Two Numbers(中等) /** * Definition for singly-linked list. * struct ListNode { * int val; * Lis ...
- AttributeError: 'dict' object has no attribute 'iteritems'
在python3.6中运行 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse= ...
- Websocket实现群聊、单聊
Websocket 使用的第三方模块:gevent-websocket 群聊 ws群聊.py中的内容 from flask import Flask, request, render_template ...
- 项目的发布(nginx、uwsgi、django、virtualenv、supervisor)
导论 WSGI是Web服务器网关接口.它是一个规范,描述了Web服务器如何与Web应用程序通信,以及Web应用程序如何链接在一起以处理一个请求,(接收请求,处理请求,响应请求) 基于wsgi运行的框架 ...