用.NET 2.0压缩/解压功能处理大型数据_实用技巧

摘要 如果你的应用程序从未使用过压缩,那么你很幸运。而对于另一部分使用压缩的开发人员来说,好消息是,.NET 2.0如今提供了两个类来处理压缩和解压问题。本文正是想讨论何时以及如何使用这些有用的工具。

引言

.NET框架2.0中的一个新名称空间是System.IO.Compression。这个新名称空间提供了两个数据压缩类:DeflateStream和GZipStream。这两个压缩类都支持无损压缩和解压,其设计目的是为了处理流式数据的压缩和解压问题。

压缩是减少数据大小的有效办法。例如,如果你有巨大量的数据存储在你的SQL数据库中,那么如果你在把这些数据保存到一个表之前压缩一下,你就可以节省大量的磁盘空间。而且,既然现在你把更小块的数据保存到你的数据库中,花费在磁盘I/O方面的操作将会大大减少。压缩的缺点是,它要求你的机器进行另外的处理(因此需要另外的处理时间),并且,在你决定把压缩应用于你的程序之前,你需要计算这一部分时间。

压缩在你需要在网上传送数据的情况中是极其有用的,特别是对于非常慢且代价昂贵的网络,例如GPRS连接。在这种情况中,使用压缩能够极大地缩小数据尺寸并且减少整个通讯耗费。Web服务是另一个领域-此时,使用压缩能提供巨大的优点,因为XML数据能被高度压缩。

但是一旦你认为程序的性能代价值得使用压缩,那么你将需要深入地理解.NET 2.0的两个新的压缩类,而这正是我想在本文中所阐述的。

创建示例应用程序

在本文中,我将构建一个示例应用程序来展示压缩的使用。该应用程序允许你压缩文件,包括普通文本文件。然后,你能够把该示例中的代码重用于你自己的应用程序中。

首先,使用Visual Studio 2005创建一个新的Windows应用程序并且使用下列控件来填充默认的表单(见图1):



图1.填充表单:使用所有显示的控件填充默认的Form1。

· GroupBox控件

· RadioButton控件

· TextBox控件

· Button控件

· Label控件

切换到Form1的code-behind并且导入下列名称空间:

Imports System.IO

Imports System.IO.Compression

在你开始使用压缩类前,理解其工作原理是非常重要的。这些压缩类从一个字节数组中读取数据,压缩它并且把结果存储到一个流对象中。对于解压来说,解压存储到一个流对象中的数据,然后把它存储到另一个流对象中。

首先,定义Compress()函数,它有两个参数:algo和data。第一个参数指定使用哪种算法(GZip或Deflate);第二个参数是一个包含要压缩的数据的字节数组。一个内存流对象将被用来存储压缩数据。一旦压缩完成,你需要计算压缩比,这是用压缩的数据的大小除以解压数据的大小计算的。

然后,存储在内存流中的压缩的数据被复制到另一个字节数组中并且被返回到调用函数。另外,你还要使用一个StopWatch对象来跟踪该压缩算法使用了多少时间。Compress()函数定义如下:

Public Function Compress(ByVal algo As String, ByVal data() As Byte) As Byte()

Try

Dim sw As New Stopwatch

'---ms用于存储压缩的数据---

Dim ms As New MemoryStream()

Dim zipStream As Stream = Nothing

'---开始秒表计时---

sw.Start()

If algo = "Gzip" Then

zipStream = New GZipStream(ms, CompressionMode.Compress, True)

ElseIf algo = "Deflate" Then

zipStream = New DeflateStream(ms, CompressionMode.Compress, True)

End If

'---使用存储在数据中的信息进行压缩---

zipStream.Write(data, 0, data.Length)

zipStream.Close()

'---停止秒表---

sw.Stop()

'---计算压缩比---

Dim ratio As Single = Math.Round((ms.Length / data.Length) * 100, 2)

Dim msg As String = "Original size: " & data.Length & _

", Compressed size: " & ms.Length & _

", 压缩比: " & ratio & "%" & _

", Time spent: " & sw.ElapsedMilliseconds & "ms"

lblMessage.Text = msg

ms.Position = 0

'---用来存储压缩了的数据(字节数组)---

Dim c_data(ms.Length - 1) As Byte

'---把内存流的内容读取到字节数组---

ms.Read(c_data, 0, ms.Length)

Return c_data

Catch ex As Exception

MsgBox(ex.ToString)

Return Nothing

End Try

End Function

这个Decompress()函数将解压由Compress()函数压缩的数据。第一个参数指定要使用的算法。包含压缩的数据的字节数组被作为第二个参数传递,然后它被复制到一个内存流对象中。然后,这些压缩类将解压存储在内存流中的数据,然后把解压的数据存储到另一个流对象中。为了获得解压的数据,你需要读取来自流对象的数据。这是通过使用RetrieveBytesFromStream()函数来实现的(将在后面解释)。

Decompress()函数的定义如下所示:

Public Function Decompress(ByVal algo As String, ByVal data() As Byte) As Byte()

Try

Dim sw As New Stopwatch

'---复制数据(压缩的)到ms---

Dim ms As New MemoryStream(data)

Dim zipStream As Stream = Nothing

'---开始秒表---

sw.Start()

'---使用存储在ms中的数据解压---

If algo = "Gzip" Then

zipStream = New GZipStream(ms, CompressionMode.Decompress)

ElseIf algo = "Deflate" Then

zipStream = New DeflateStream(ms, CompressionMode.Decompress, True)

End If

'---用来存储解压的数据---

Dim dc_data() As Byte

'---解压的数据存储于zipStream中;

'把它们提取到一个字节数组中---

dc_data = RetrieveBytesFromStream(zipStream, data.Length)

'---停止秒表---

sw.Stop()

lblMessage.Text = "Decompression completed. Time spent: " & _

sw.ElapsedMilliseconds & "ms" & _

", Original size: " & dc_data.Length

Return dc_data

Catch ex As Exception

MsgBox(ex.ToString)

Return Nothing

End Try

End Function

这个RetrieveBytesFromStream()函数使用了两个参数:一个流对象,一个整数,并返回一个包含解压的数据的字节数组。这个整数参数用于决定每次把多少个字节从该流对象中读取到字节数组中。这是必要的,因为当数据被解压时,你不知道存在于流对象中的解压数据的大小。因此,有必要动态地把字节数组扩展成块以便存储在运行时刻期间解压缩的数据中。当你不断地扩展字节数组时,块太大会浪费内存,而块太小则会失去珍贵的时间。因此,可以由调用例程来决定要读取的最佳块大小。

RetrieveBytesFromStream()函数的定义如下:

Public Function RetrieveBytesFromStream( _

ByVal stream As Stream, ByVal bytesblock As Integer) As Byte()

'---从一个流对象中检索字节---

Dim data() As Byte

Dim totalCount As Integer = 0

Try

While True

'---逐渐地增加数据字节数组-的大小--

ReDim Preserve data(totalCount + bytesblock)

Dim bytesRead As Integer = stream.Read(data, totalCount, bytesblock)

If bytesRead = 0 Then

Exit While

End If

totalCount += bytesRead

End While

'---确保字节数组正确包含提取的字节数---

ReDim Preserve data(totalCount - 1)

Return data

Catch ex As Exception

MsgBox(ex.ToString)

Return Nothing

End Try

End Function

注意,在Decompress()函数中,你调用了RetrieveBytesFromStream()函数,如下所示:

dc_data = RetrieveBytesFromStream(zipStream, data.Length)

块大小是指压缩的数据的大小(data.length)。在大多数情况中,解压缩的数据要比压缩的数据大几倍(由压缩比所显示),因此,在运行时刻期间你将至多动态地扩展字节数组几倍。作为一个例子,假定压缩比是百分之20而压缩的数据的大小为2MB,那么,在这种情况中,解压的数据将是10MB。因此,该字节数组将被动态地扩展5倍。理想情况下,在运行时刻期间该字节数组不应该被扩展太频繁,因为这将会严重地减慢应用程序运行速度。但是使用压缩的数据的大小作为块大小确是一种好的办法。

时间: 2024-10-23 11:22:50

用.NET 2.0压缩/解压功能处理大型数据_实用技巧的相关文章

用.NET 2.0压缩/解压功能处理大型数据

数据|压缩 摘要 如果你的应用程序从未使用过压缩,那么你很幸运.而对于另一部分使用压缩的开发人员来说,好消息是,.NET 2.0如今提供了两个类来处理压缩和解压问题.本文正是想讨论何时以及如何使用这些有用的工具. 引言 .NET框架2.0中的一个新名称空间是System.IO.Compression.这个新名称空间提供了两个数据压缩类:DeflateStream和GZipStream.这两个压缩类都支持无损压缩和解压,其设计目的是为了处理流式数据的压缩和解压问题. 压缩是减少数据大小的有效办法.

ASP.NET 文件压缩解压类(C#)_实用技巧

本文实例讲述了asp.net C#实现解压缩文件的方法,需要引用一个ICSharpCode.SharpZipLib.dll,供大家参考,具体如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using ICSharpCode.SharpZipLib.Zip; using System.IO; using ICSharpCode.SharpZipLib.Checksum

asp.net 不用GridView自带删除功能,删除一行数据_实用技巧

前台代码: 复制代码 代码如下: <asp:GridView ID="GridLog" runat="server" AutoGenerateColumns="False" CellPadding="4" DataKeyNames="ID" BorderColor="#333" BorderStyle="solid" BorderWidth="1&qu

Asp.net 2.0 C#实现压缩/解压功能 (示例代码下载)

asp.net|示例|下载|压缩 (一). 实现功能    对文件及目录的压缩及解压功能(二). 运行图片示例  (三).代码    1. 压缩类     1/**//// <summary>  2/// 压缩类  3/// </summary>  4public class ZipClass  5{     6    public static void ZipFile(string FileToZip, string ZipedFile, int CompressionLeve

ASP.NET MVC5网站开发之业务逻辑层的架构和基本功能 (四)_实用技巧

业务逻辑层在Ninesky.Core中实现,主要功能封装一些方法通过调用数据存储层,向界面层提供服务. 一.业务逻辑层的架构 Ninesky.Core包含三个命名空间Ninesky.Core.Ninesky.Core.Types.Ninesky.Core.General. Ninesky.Core包含模型和功能实现,Ninesky.Core.Types是项目用到的一些类型的定义,Ninesky.Core.General是项目用到的一些方法的定义. 1.Ninesky.Core命名空间的结构 Ni

详解.NET中使用Redis数据库_实用技巧

Redis是一个用的比较广泛的Key/Value的内存数据库,新浪微博.Github.StackOverflow 等大型应用中都用其作为缓存,Redis的官网为http://redis.io/. 最近项目中需要使用Redis,这里简单记录一下Redis的安装,以及如何在.NET中使用Redis. Redis安装与启动 1. 下载Redis Redis本身没有提供Windows版本的,并且在Windows上也不太稳定,一般都将其部署到Linux环境下,Redis可以在其官网上下载, MSOpenT

Asp.net在线备份、压缩和修复Access数据库示例代码_实用技巧

1.问题的提出 在设计中小型Web应用程序时,可以选择Microsoft Accesss为数据库.在数据库的使用过程中经常性进行增加和删除操作.事实上,Microsoft Access并不能有效地释放已分配的但被删除的对象空间,这将意味着即使你删除了一个对象,而这个对象仍然占据着数据库的空间,使得数据库越来越大.不但占用不必要的空间,而且降低了数据库的效率.特别在虚拟站点上的问题尤为突出.因此对Access数据库进行压缩瘦身很有实际意义. 虽然Access数据库自身具有"压缩和修复数据库&quo

深入Lumisoft.NET组件与.NET API实现邮件发送功能的对比分析_实用技巧

我在另一篇文章<深入Lumisoft.NET实现邮件发送功能的方法详解>有大致对这个Lumisoft.NET组件的使用进行了介绍,当然Lumisoft.NET组件除了提供邮件发送功能外,还提供了邮件接收等功能的处理(包括基于POP3协议和IMAP协议),而.NET则除了提供SMTP协议功能外,则没有提供POP3协议处理的相关类库,因此收取邮件这需要自己进行封装(需要也可以参考codeproject.com上的相关文章). 1..NET的邮件发送功能实现.NET本身封装了一个SmtpClient

详解.net mvc session失效问题_实用技巧

最近在研究有关.net mvc项目中的session失效问题,下面小编把研究过程给大家共享下,大家可以参考下. 最近解决基于.net mvc项目的session失效问题,这个跟大家聊聊. 1.问题分析 .net mvc中,Session失效需要考虑几种情况: •基于权限认证的Action,使用非Ajax请求: •基于权限认证的Action,使用JQueryt Ajax请求: •基于权限认证的Action,使用.net mvc封装的Ajax请求: •无权限认证的Action,使用非Aajx请求: