http://www.microsoft.com/taiwan/msdn/columns/adonet/AdoNet_20041231.htm
ADO.NET 1.x Dataset 序列化問題探討
http://support.microsoft.com/?kbid=829740
提高 DataSet 序列化和远程处理性能
利用SharpZipLib进行压缩和解压缩 [原]
因为工作需要所以要用C#写一个压缩解压缩的程序,从网上搜索大概有那么三种方式,1、调用winrar的接口函数来实现,缺点是必须安装winrar所以不具有通用性。2、msdn说的(使用 J# 类库中的 Zip 类压缩文件和数据)3、就是利用SharpZipLib进行压缩和解压缩这个是一家公司开发的可以用于封装在商业用途的软件中的.net类。下载地址http://www.icsharpcode.net/ 从壓縮包里面将ICSharpCode.SharpZipLib.dll文件引入.net程序即可使用。在写这个类的时候参考了csdn一个网友写的类,他的类只能压缩活页夹下面的文件,而不能压缩子目录及其子目录下面的文件,解压的时候只能解压没有子目录的压缩包。所以我将它作了改进,使之能够压缩子目录及其文件和能够解压带有子目录及其文件的压缩包。下面是程序代码及其注释。
/// 以下为ZipClass即是压缩类
using System;
using System.IO;
using ICSharpCode.SharpZipLib.Checksums;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.GZip;
namespace Webpos
{
public class ZipClass
{
public string cutStr = "";
#region 这个函数我没有去研究他
public void ZipFile(string FileToZip, string ZipedFile ,int CompressionLevel, int BlockSize)
{
//如果文件没有找到则报错。
if (! System.IO.File.Exists(FileToZip))
{
throw new System.IO.FileNotFoundException("The specified file " + FileToZip + " could not be found. Zipping aborderd";
}
System.IO.FileStream StreamToZip = new System.IO.FileStream(FileToZip,System.IO.FileMode.Open , System.IO.FileAccess.Read);
System.IO.FileStream ZipFile = System.IO.File.Create(ZipedFile);
ZipOutputStream ZipStream = new ZipOutputStream(ZipFile);
ZipEntry ZipEntry = new ZipEntry("ZippedFile";
ZipStream.PutNextEntry(ZipEntry);
ZipStream.SetLevel(CompressionLevel);
byte[] buffer = new byte[BlockSize];
System.Int32 size =StreamToZip.Read(buffer,0,buffer.Length);
ZipStream.Write(buffer,0,size);
try
{
while (size < StreamToZip.Length)
{
int sizeRead =StreamToZip.Read(buffer,0,buffer.Length);
ZipStream.Write(buffer,0,sizeRead);
size += sizeRead;
}
}
catch(System.Exception ex)
{
throw ex;
}
ZipStream.Finish();
ZipStream.Close();
StreamToZip.Close();
}
#endregion
//Get all DirectoryInfo
private void direct(DirectoryInfo di,ref ZipOutputStream s,Crc32 crc)
{
//DirectoryInfo di = new DirectoryInfo(filenames);
DirectoryInfo[] dirs = di.GetDirectories("*";
//遍历目录下面的所有的子目录
foreach(DirectoryInfo dirNext in dirs)
{
//将该目录下的所有文件添加到 ZipOutputStream s 压缩流里面
FileInfo[] a = dirNext.GetFiles();
this.writeStream( ref s,a,crc ;
//递归调用直到把所有的目录遍历完成
direct(dirNext,ref s,crc);
}
}
private void writeStream(ref ZipOutputStream s,FileInfo[] a,Crc32 crc)
{
foreach ( FileInfo fi in a
{
//string fifn = fi.FullName;
FileStream fs = fi.OpenRead();
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
//ZipEntry entry = new ZipEntry(file); Path.GetFileName(file)
string file = fi.FullName;
file = file.Replace(cutStr,"";
ZipEntry entry = new ZipEntry(file);
entry.DateTime = DateTime.Now;
// set Size and the crc, because the information
// about the size and crc should be stored in the header
// if it is not set it is automatically written in the footer.
// (in this case size == crc == -1 in the header)
// Some ZIP programs have problems with zip files that don't store
// the size and crc in the header.
entry.Size = fs.Length;
fs.Close();
crc.Reset();
crc.Update(buffer);
entry.Crc = crc.Value;
s.PutNextEntry(entry);
s.Write(buffer, 0, buffer.Length);
}
}
/// <summary>
/// 主调函数
/// </summary>
/// <param name="args">args[0]为你要压缩的目录所在的路径
/// 例如:D:\\temp\\ (注意temp 后面加 \\ 但是你写程序的时候怎么修改都可以)
/// args[1]为压缩后的文件名及其路径
/// 例如:D:\\temp.zip
/// </param>
public void ZipFileMain(string[] args)
{
//string filenames = Directory.GetFiles(args[0]);
Crc32 crc = new Crc32();
ZipOutputStream s = new ZipOutputStream(File.Create(args[1]));
s.SetLevel(6); // 0 - store only to 9 - means best compression
DirectoryInfo di = new DirectoryInfo(args[0]);
FileInfo[] a = di.GetFiles();
cutStr = args[0].Trim();
//压缩这个目录下的所有文件
writeStream(ref s,a,crc);
//压缩这个目录下子目录及其文件
direct(di,ref s,crc);
s.Finish();
s.Close();
}
}
}
///下面是解压缩文件的类
using System;
using System.Text;
using System.Collections;
using System.IO;
using System.Diagnostics;
using System.Runtime.Serialization.Formatters.Binary;
using System.Data;
using ICSharpCode.SharpZipLib.BZip2;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Zip.Compression;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
using ICSharpCode.SharpZipLib.GZip;
namespace Webpos
{
public class UnZipClass
{
public void UnZip(string[] args)
{
ZipInputStream s = new ZipInputStream(File.OpenRead(args[0]));
ZipEntry theEntry;
while ((theEntry = s.GetNextEntry()) != null)
{
string directoryName = Path.GetDirectoryName(args[1]);
string fileName = Path.GetFileName(theEntry.Name);
//生成解压目录
Directory.CreateDirectory(directoryName);
if (fileName != String.Empty)
{
//如果文件的壓縮後的大小為0那麼說明這個文件是空的因此不需要進行讀出寫入
if( theEntry.CompressedSize == 0
break;
//解压文件到指定的目录
directoryName = Path.GetDirectoryName(args[1]+theEntry.Name);
//建立下面的目录和子目录
Directory.CreateDirectory(directoryName);
FileStream streamWriter = File.Create(args[1]+theEntry.Name);
int size = 2048;
byte[] data = new byte[2048];
while (true)
{
size = s.Read(data, 0, data.Length);
if (size > 0)
{
streamWriter.Write(data, 0, size);
}
else
{
break;
}
}
streamWriter.Close();
}
}
s.Close();
}
}
}
对于在WebService上必须(无法避免的情况下)要传输大量数据的DataSet时,对DataSet压缩是最好的方法,这样可以减少大量在网络传输过程中所占用的时间。
下面对我掌握的的DataSet压缩方法做一个测试,希望高人有斧正之处,也希望需要的人有借鉴之处。
注:经过压缩DataSet的WebService就缺少了通用性,请权衡使用之。
测试源码(仅压缩部分)和结果如下:
条件:压缩前的DataSet的大小为16891323字节(大约16.12M)。
环境:.Net Formatwork 1.1
系统: Windows XP SP1
硬件:P4(2.4G) + 256DDR
方案1:DataSetSurrogate + BinaryFormatter
Public Function DataSetToByte(ByVal DataSet As DataSet) As Byte()
Dim DSS As New DataSetSurrogate(DataSet)
Dim MS As New IO.MemoryStream
Dim BF As New BinaryFormatter
BF.Serialize(MS, DSS)
Dim ReVal() As Byte = MS.ToArray()
MS.Close()
DSS = Nothing
MS = Nothing
BF = Nothing
Return ReVal
End Function
方案2:DataSetSurrogate + BinaryFormatter + SharpZipLib
Public Function DataSetToByte(ByVal DataSet As DataSet) As Byte()
Dim MS As New IO.MemoryStream
Dim ZOS As New ZipOutputStream(MS)
ZOS.PutNextEntry(New ZipEntry(DataSet.DataSetName))
Dim BF As New BinaryFormatter
Dim DSS As DataSetSurrogate = New DataSetSurrogate(DataSet)
BF.Serialize(ZOS, DSS)
ZOS.CloseEntry()
ZOS.Close()
Dim ReVal As Byte() = MS.ToArray
MS.Close()
MS = Nothing
ZOS = Nothing
BF = Nothing
DSS = Nothing
Return ReVal
End Function
方案3:zlib
Public Function DataSetToByte(ByVal DataSet As DataSet) As Byte()
Dim MS As New System.IO.MemoryStream
DataSet.WriteXml(MS, XmlWriteMode.WriteSchema)
Dim ReVal() As Byte = MS.ToArray
MS.Close()
MS = Nothing
Dim zlib As New vbZLib.Compress
zlib.CompressByte(ReVal)
zlib = Nothing
Return ReVal
End Function
结果(压缩后):
方案1:4420881字节(被压缩掉大约73.83%),耗时:23200ms
方案2: 696881字节(被压缩掉大约95.87%),耗时:26621ms
方案3: 422990字节(被压缩掉大约97.50%),耗时: 680ms
看来,无论压缩率还是耗时都是方案3最优,但是使用了第三方组件。前两个方案对CPU资源占用率的也让人无法接受。
http://www.zlib.net/zlib.html的下载地址