精灵巫婆 发表于 2015-1-16 22:42:20

ASP.NET编程:用.NET 2.0紧缩/解压功能处置年夜型数据

另外,小型软件代码重用价值低,没有必要跨平台;大型软件,有严格的规划、部署,不可以随意跨平台。数据|紧缩  择要假如你的使用程序从未利用过紧缩,那末你很侥幸。而关于另外一部分利用紧缩的开辟职员来讲,好动静是,.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使用程序中到场紧缩功效。
以前很热炒跨平台,主要是由于硅谷挑战微软霸主地位的热情,但是冷静下来后,跨平台往往不是那么一回事。假设你有个软件,所谓的跨平台,你只需要为第二个平台上重新编译一次就行了,这样很难么?

小女巫 发表于 2015-1-17 14:16:12

以上是语言本身的弱点,在功能方面ASP同样存在问题,第一是功能太弱,一些底层操作只能通过组件来完成,在这点上是远远比不上PHP/JSP,其次就是缺乏完善的纠错/调试功能,这点上ASP/PHP/JSP差不多。

透明 发表于 2015-1-20 19:13:52

这也就是最近几年来随着各种新的后台技术的诞生,CGI应用在Internet上越来越少的原因。CGI方式不适合大访问量的应用。

再见西城 发表于 2015-1-29 15:45:57

通过这次激烈的讨论,我从大家身上学到了太多,开阔了眼界,不管是支持我的还是骂我的,都感谢你们。

精灵巫婆 发表于 2015-2-6 02:37:40

同时也感谢博客园给我们这个平台,也感谢博客园的编辑们做成专题引来这么多高人指点。

冷月葬花魂 发表于 2015-2-15 02:13:58

平台无关性是PHP的最大优点,但是在优点的背后,还是有一些小小的缺点的。如果在PHP中不使用ODBC,而用其自带的数据库函数(这样的效率要比使用ODBC高)来连接数据库的话,使用不同的数据库,PHP的函数名不能统一。这样,使得程序的移植变得有些麻烦。不过,作为目前应用最为广泛的一种后台语言,PHP的优点还是异常明显的。

愤怒的大鸟 发表于 2015-3-11 18:32:17

主流网站开发语言之ASP:ASP是微软(Microsoft)所开发的一种后台脚本语言,它的语法和VisualBASIC类似,可以像SSI(ServerSideInclude)那样把后台脚本代码内嵌到HTML页面中。虽然ASP简单易用,但是它自身存在着许多缺陷,最重要的就是安全性问题。

变相怪杰 发表于 2015-3-19 07:33:41

代码逻辑混乱,难于管理:由于ASP是脚本语言混合html编程,所以你很难看清代码的逻辑关系,并且随着程序的复杂性增加,使得代码的管理十分困难,甚至超出一个程序员所能达到的管理能力,从而造成出错或这样那样的问题。

仓酷云 发表于 2015-3-27 13:58:03

但是java靠开源打出的一片天地,特别是在微软的垄断下能打开今天的局面还是有它的生命力的。
页: [1]
查看完整版本: ASP.NET编程:用.NET 2.0紧缩/解压功效处置年夜型数据