專案需將 DataSet 序列化為檔案並上傳伺服器,原始二進位檔案過大,引入 GZipStream 壓縮後效果顯著。以下整理完整可用代碼。
using System.Data;
using System.IO;
using System.IO.Compression;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
namespace DataSetSerializerDeserialize
{
class Program
{
/// 序列化 DataSet 並以 GZip 壓縮寫入檔案
static void DataSetSerializerCompression(DataSet ds)
{
IFormatter formatter = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
formatter.Serialize(ms, ds);
byte[] buffer = ms.ToArray();
using (FileStream fs = File.Create("datasetCompression.dat"))
using (GZipStream gzip = new GZipStream(fs, CompressionMode.Compress, true))
{
gzip.Write(buffer, 0, buffer.Length);
// 必須關閉 gzip 才能正確刷新壓縮資料塊,否則解壓時 <4KB 檔案讀取失敗
}
}
}
/// 直接序列化 DataSet 不壓縮
static void DataSetSerializer(DataSet ds)
{
IFormatter formatter = new BinaryFormatter();
using (FileStream fs = File.Create("dataset.dat"))
formatter.Serialize(fs, ds);
}
static void Main(string[] args)
{
// 建立測試資料:101 列
DataTable table = new DataTable("ParentTable");
table.Columns.Add("id", typeof(int));
table.Columns.Add("ParentItem", typeof(string));
table.PrimaryKey = new[] { table.Columns["id"] };
DataSet dataSet = new DataSet();
dataSet.Tables.Add(table);
for (int i = 0; i <= 100; i++)
{
var row = table.NewRow();
row["id"] = i;
row["ParentItem"] = "ParentItem " + i;
table.Rows.Add(row);
}
DataSetSerializer(dataSet); // 無壓縮
DataSetSerializerCompression(dataSet); // 壓縮
}
}
}
BinaryFormatter:將物件圖序列化為二進位格式,支援 DataSet 完整結構MemoryStream 當中介緩衝,避免邊序列化邊壓縮的流控制複雜度GZipStream(..., true):leaveOpen=true 讓外層 using 統一管理 FileStream 生命週期GZipStream:未正確關閉會導致壓縮資料塊不完整,解壓時小檔案 (<4KB) 讀取失敗、大檔案資料截斷測試資料 101 列,無壓縮約 45 KB,GZip 後約 4 KB,**壓縮率超 90%**。下一篇將補充解壓還原代碼。
