马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
另外,小型软件代码重用价值低,没有必要跨平台;大型软件,有严格的规划、部署,不可以随意跨平台。数据|紧缩 择要假如你的使用程序从未利用过紧缩,那末你很侥幸。而关于另外一部分利用紧缩的开辟职员来讲,好动静是,.NET2.0现在供应了两个类来处置紧缩息争压成绩。本文恰是想会商什么时候和怎样利用这些有效的工具。
弁言
.NET框架2.0中的一个新称号空间是System.IO.Compression。这个新称号空间供应了两个数据紧缩类:DeflateStream和GZipStream。这两个紧缩类都撑持无损紧缩息争压,其计划目标是为了处置流式数据的紧缩息争压成绩。
紧缩是削减数据巨细的无效举措。比方,假如你有伟大量的数据存储在你的SQL数据库中,那末假如你在把这些数据保留到一个表之前紧缩一下,你就能够节俭大批的磁盘空间。并且,既然如今你把更小块的数据保留到你的数据库中,消费在磁盘I/O方面的操纵将会年夜年夜削减。紧缩的弱点是,它请求你的呆板举行别的的处置(因而必要别的的处置工夫),而且,在你决意把紧缩使用于你的程序之前,你必要盘算这一部分工夫。
紧缩在你必要在网上传送数据的情形中是极为有效的,出格是关于十分慢且价值高贵的收集,比方GPRS毗连。在这类情形中,利用紧缩可以极年夜地减少数据尺寸而且削减全部通信泯灭。Web服务是另外一个范畴-此时,利用紧缩能供应伟大的长处,由于XML数据能被高度紧缩。
可是一旦你以为程序的功能价值值得利用紧缩,那末你将必要深切地舆解.NET2.0的两个新的紧缩类,而这恰是我想在本文中所论述的。
创立示例使用程序
在本文中,我将构建一个示例使用程序来展现紧缩的利用。该使用程序同意你紧缩文件,包含一般文本文件。然后,你可以把该示例中的代码重用于你本人的使用程序中。
起首,利用VisualStudio2005创立一个新的Windows使用程序而且利用以下控件来添补默许的表单(见):
.添补表单:利用一切显现的控件添补默许的Form1。
・GroupBox控件
・RadioButton控件
・TextBox控件
・Button控件
・Label控件
切换到Form1的code-behind而且导进以下称号空间:
ImportsSystem.IO
ImportsSystem.IO.Compression
在你入手下手利用紧缩类前,了解其事情道理长短常主要的。这些紧缩类从一个字节数组中读取数据,紧缩它而且把了局存储到一个流工具中。关于解压来讲,解压存储到一个流工具中的数据,然后把它存储到另外一个流工具中。
起首,界说Compress()函数,它有两个参数:algo和data。第一个参数指定利用哪一种算法(GZip或Deflate);第二个参数是一个包括要紧缩的数据的字节数组。一个内存流工具将被用来存储紧缩数据。一旦紧缩完成,你必要盘算紧缩比,这是用紧缩的数据的巨细除以解压数据的巨细盘算的。
然后,存储在内存流中的紧缩的数据被复制到另外一个字节数组中而且被前往到挪用函数。别的,你还要利用一个StopWatch工具来跟踪该紧缩算法利用了几工夫。Compress()函数界说以下:
PublicFunctionCompress(ByValalgoAsString,ByValdata()AsByte)AsByte()
Try
DimswAsNewStopwatch
---ms用于存储紧缩的数据---
DimmsAsNewMemoryStream()
DimzipStreamAsStream=Nothing
---入手下手秒表计时---
sw.Start()
Ifalgo="Gzip"Then
zipStream=NewGZipStream(ms,CompressionMode.Compress,True)
ElseIfalgo="Deflate"Then
zipStream=NewDeflateStream(ms,CompressionMode.Compress,True)
EndIf
---利用存储在数据中的信息举行紧缩---
zipStream.Write(data,0,data.Length)
zipStream.Close()
---中断秒表---
sw.Stop()
---盘算紧缩比---
DimratioAsSingle=Math.Round((ms.Length/data.Length)*100,2)
DimmsgAsString="Originalsize:"&data.Length&_
",Compressedsize:"&ms.Length&_
",紧缩比:"&ratio&"%"&_
",Timespent:"&sw.ElapsedMilliseconds&"ms"
lblMessage.Text=msg
ms.Position=0
---用来存储紧缩了的数据(字节数组)---
Dimc_data(ms.Length-1)AsByte
---把内存流的内容读取到字节数组---
ms.Read(c_data,0,ms.Length)
Returnc_data
CatchexAsException
MsgBox(ex.ToString)
ReturnNothing
EndTry
EndFunction
这个Decompress()函数将解压由Compress()函数紧缩的数据。第一个参数指定要利用的算法。包括紧缩的数据的字节数组被作为第二个参数传送,然后它被复制到一个内存流工具中。然后,这些紧缩类将解压存储在内存流中的数据,然后把解压的数据存储到另外一个流工具中。为了取得解压的数据,你必要读取来自流工具的数据。这是经由过程利用RetrieveBytesFromStream()函数来完成的(将在前面注释)。
Decompress()函数的界说以下所示:
PublicFunctionDecompress(ByValalgoAsString,ByValdata()AsByte)AsByte()
Try
DimswAsNewStopwatch
---复制数据(紧缩的)到ms---
DimmsAsNewMemoryStream(data)
DimzipStreamAsStream=Nothing
---入手下手秒表---
sw.Start()
---利用存储在ms中的数据解压---
Ifalgo="Gzip"Then
zipStream=NewGZipStream(ms,CompressionMode.Decompress)
ElseIfalgo="Deflate"Then
zipStream=NewDeflateStream(ms,CompressionMode.Decompress,True)
EndIf
---用来存储解压的数据---
Dimdc_data()AsByte
---解压的数据存储于zipStream中;
把它们提取到一个字节数组中---
dc_data=RetrieveBytesFromStream(zipStream,data.Length)
---中断秒表---
sw.Stop()
lblMessage.Text="Decompressioncompleted.Timespent:"&_
sw.ElapsedMilliseconds&"ms"&_
",Originalsize:"&dc_data.Length
Returndc_data
CatchexAsException
MsgBox(ex.ToString)
ReturnNothing
EndTry
EndFunction
这个RetrieveBytesFromStream()函数利用了两个参数:一个流工具,一个整数,并前往一个包括解压的数据的字节数组。这个整数参数用于决意每次把几个字节从该流工具中读取到字节数组中。这是需要的,由于当数据被解压时,你不晓得存在于流工具中的解压数据的巨细。因而,有需要静态地把字节数组扩大成块以便存储在运转时候时代解紧缩的数据中。当你不休地扩大字节数组时,块太年夜会华侈内存,而块太小则会得到可贵的工夫。因而,能够由挪用例程来决意要读取的最好块巨细。
RetrieveBytesFromStream()函数的界说以下:
PublicFunctionRetrieveBytesFromStream(_
ByValstreamAsStream,ByValbytesblockAsInteger)AsByte()
---从一个流工具中检索字节---
Dimdata()AsByte
DimtotalCountAsInteger=0
Try
WhileTrue
---渐渐地增添数据字节数组-的巨细--
ReDimPreservedata(totalCount+bytesblock)
DimbytesReadAsInteger=stream.Read(data,totalCount,bytesblock)
IfbytesRead=0Then
ExitWhile
EndIf
totalCount+=bytesRead
EndWhile
---确保字节数组准确包括提取的字节数---
ReDimPreservedata(totalCount-1)
Returndata
CatchexAsException
MsgBox(ex.ToString)
ReturnNothing
EndTry
EndFunction
注重,在Decompress()函数中,你挪用了RetrieveBytesFromStream()函数,以下所示:
dc_data=RetrieveBytesFromStream(zipStream,data.Length)
块巨细是指紧缩的数据的巨细(data.length)。在年夜多半情形中,解紧缩的数据要比紧缩的数据年夜几倍(由紧缩比所显现),因而,在运转时候时代你将最多静态地扩大字节数组几倍。作为一个例子,假定紧缩比是百分之20而紧缩的数据的巨细为2MB,那末,在这类情形中,解压的数据将是10MB。因而,该字节数组将主动态地扩大5倍。幻想情形下,在运转时候时代该字节数组不该该被扩大太频仍,由于这将会严峻地减慢使用程序运转速率。可是利用紧缩的数据的巨细作为块巨细确是一种好的举措。
<P> 处置紧缩事务
如今,既然界说好了次要的紧缩息争压例程,那末接上去你就能够为各类按钮举行编码了。响应于Compress按钮的事务处置器以下:
PrivateSubbtnCompress_Click(ByValsenderAsSystem.Object,_
ByValeAsSystem.EventArgs)HandlesbtnCompress.Click
---用来存储紧缩的数据---
DimcompressedData()AsByte
---紧缩数据---
IfrbGZipStream.CheckedThen
compressedData=Compress("Gzip",System.Text.Encoding.ASCII.GetBytes(txtBefore.Text))
Else
compressedData=Compress("Deflate",System.Text.Encoding.ASCII.GetBytes(txtBefore.Text))
EndIf
---把紧缩的数据复制到一个字符串中---
DimiAsInteger
DimsAsNewSystem.Text.StringBuilder()
Fori=0TocompressedData.Length-1
IficompressedData.Length-1Then
s.Append(compressedData(i)&"")
Else
s.Append(compressedData(i))
EndIf
Next
---显现紧缩的数据为一个字符串---
txtAfter.Text=s.ToString
EndSub
在txtBefore控件中的数据被转换成一个字节数组,然后被紧缩。然后,该紧缩的数据被转换成字符串以便于在txtAfter中显现。
响应于Decompress按钮的事务处置器以下:
PrivateSubbtnDecompress_Click(ByValsenderAsSystem.Object,_
ByValeAsSystem.EventArgs)HandlesbtnDecompress.Click
---把紧缩的字符串格局化成一个字节数组---
Dimeachbyte()AsString=txtAfter.Text.Split("")
Dimdata(eachbyte.Length-1)AsByte
ForiAsInteger=0Toeachbyte.Length-1
data(i)=Convert.ToByte(eachbyte(i))
Next
---解压数据而且显现解压的数据---
IfrbGZipStream.CheckedThen
txtBefore.Text=System.Text.Encoding.ASCII.GetString(Decompress("Gzip",data))
Else
txtBefore.Text=System.Text.Encoding.ASCII.GetString(Decompress("Deflate",data))
EndIf
EndSub
它把显现在控件txtAfter中的数据转换成一个字节数组,然后发送它以便举行解压。解紧缩的数据被显现回txtBefore控件中。
响应于"Selectfiletocompress"按钮的事务处置器代码以下:
PrivateSubbtnSelectFile_Click(ByValsenderAsSystem.Object,_
ByValeAsSystem.EventArgs)HandlesbtnSelectFile.Click
---让用户选择一个要紧缩的文件--
DimopenFileDialog1AsNewOpenFileDialog()
openFileDialog1.InitialDirectory="c:"
openFileDialog1.Filter="Allfiles(*.*)|*.*"
openFileDialog1.RestoreDirectory=True
IfopenFileDialog1.ShowDialog()=Windows.Forms.DialogResult.OKThen
---把文件的内容读进字节数组---
DimfileContentsAsByte()
fileContents=My.Computer.FileSystem.ReadAllBytes(openFileDialog1.FileName)
---创立gzip文件---
DimfilenameAsString=openFileDialog1.FileName&".gzip"
IfFile.Exists(filename)ThenFile.Delete(filename)
DimfsAsFileStream=NewFileStream(filename,FileMode.CreateNew,FileAccess.Write)
---紧缩文件的内容---
Dimcompressed_DataAsByte()
IfrbGZipStream.CheckedThen
compressed_Data=Compress("Gzip",fileContents)
Else
compressed_Data=Compress("Deflate",fileContents)
EndIf
Ifcompressed_DataIsNotNothingThen
---把紧缩的内容写进紧缩的文件中---
fs.Write(compressed_Data,0,compressed_Data.Length)
fs.Close()
EndIf
EndIf
EndSub
它读取由用户选择的文件的内容,紧缩它,而且创立一个包括紧缩的数据的新文件(具有一样的文件名,可是加上了一个.gzip扩大名)。
响应于"SelectfiletoDecompress"按钮的事务处置器代码以下:
PrivateSubbtnDecompressFile_Click(ByValsenderAsSystem.Object,_
ByValeAsSystem.EventArgs)HandlesbtnDecompressFile.Click
---让用户选择一个要解压的文件---
DimopenFileDialog1AsNewOpenFileDialog()
openFileDialog1.InitialDirectory="c:"
openFileDialog1.Filter="AllGZIPfiles(*.gzip)|*.gzip"
openFileDialog1.RestoreDirectory=True
IfopenFileDialog1.ShowDialog()=Windows.Forms.DialogResult.OKThen
---把紧缩的文件的内容读进到字节数组---
DimfileContentsAsByte()
fileContents=My.Computer.FileSystem.ReadAllBytes(openFileDialog1.FileName)
---解压文件的内容---
Dimuncompressed_DataAsByte()
IfrbGZipStream.CheckedThen
uncompressed_Data=Decompress("Gzip",fileContents)
Else
uncompressed_Data=Decompress("Deflat",fileContents)
EndIf
---创立解压的文件---
DimfilenameAsString=openFileDialog1.FileName.Substring(0,openFileDialog1.FileName.Length-5)
IfFile.Exists(filename)ThenFile.Delete(filename)
DimfsAsFileStream=NewFileStream(filename,FileMode.CreateNew,FileAccess.Write)
Ifuncompressed_DataIsNotNothingThen
---把解压内容写进到文件中---
fs.Write(uncompressed_Data,0,uncompressed_Data.Length)
fs.Close()
EndIf
EndIf
EndSub
它读取用户选择的文件的内容,解压之,而且创立一个包括解压的数据的新文件(经由过程往失落它的.gzip扩大名)。
<P> 测试使用程序
按F5测试使用程序(见)。
.测试使用程序:选择利用的紧缩算法,然后你能够紧缩一个文本串或一个文件内容。
你应当注重以下现实:
・紧缩小数目的文本实践大将会招致一种较年夜的紧缩文本。
・分歧的文本将发生分歧的紧缩比,只管字符数是流动的。
・文本文件紧缩效果最好;它们可以带来最好的紧缩比。
・别的二进制的文件,比方.exe,jpg,一般紧缩效果其实不很好而且大概会招致年夜于百分比之100的紧缩比,这是没有代价的。
必要注重的是,.NET中的GZIP和Deflate算法的完成要比市场上的别的第三方GZIP工具具有较低的效力。只管你可以利用.NET类把10MB的数据紧缩到4MB,可是你发明利用一种第三方工具大概会到达一种更小的紧缩巨细。别的,这个紧缩类没法操纵年夜于4GB的数据。但是,在.NET中的完成将同意你解压利用市场中的别的GZIP工具紧缩的一切的文件。
小结
在本文中,你已看到了怎样在.NET2.0中利用紧缩类。只管这类完成还不如市场上的那些非MS计划无效,可是它切实其实为你供应了一种简单(收费)的体例来在你的.NET使用程序中到场紧缩功效。
以前很热炒跨平台,主要是由于硅谷挑战微软霸主地位的热情,但是冷静下来后,跨平台往往不是那么一回事。假设你有个软件,所谓的跨平台,你只需要为第二个平台上重新编译一次就行了,这样很难么? |