.net的序列化與反序列化實(shí)例
本文實(shí)例講述了.net的序列化與反序列化的實(shí)現(xiàn)方法。分享給大家供大家參考。具體方法如下:
1.序列化與反序列化概述
C#中如果需要:將一個(gè)結(jié)構(gòu)很復(fù)雜的類(lèi)的對(duì)象存儲(chǔ)起來(lái),或者通過(guò)網(wǎng)路傳輸?shù)竭h(yuǎn)程的客戶端程序中去,這時(shí)就需要用到序列化,反序列化(Serialization & Deserialization)
2.BinaryFormattter
.NET中串行有三種,BinaryFormatter, SoapFormatter和XmlSerializer.
其中BinaryFormattter最簡(jiǎn)單,它是直接用二進(jìn)制方式把對(duì)象 (Object)進(jìn)行串行或反串,他的優(yōu)點(diǎn)是速度快,可以串行private或者protected的member, 在不同版本的。NET中都兼容,可以看作是。NET自己的本命方法,當(dāng)然缺點(diǎn)也就隨之而來(lái)了,離開(kāi)了。NET它就活不了,所以不能在其他平臺(tái)或跨網(wǎng)路上進(jìn) 行。
3.序列化
MemoryStream ms = new MemoryStream();
ser.Serialize(ms, DS);
byte[] buffer = ms.ToArray();
MemoryStream :創(chuàng)建其支持存儲(chǔ)區(qū)為內(nèi)存的流
4.反序列化
MemoryStream ms = new MemoryStream(bytes);
BinaryFormatter ser = new BinaryFormatter();
DataSetSurrogate dss = ser.Deserialize(ms) asDataSetSurrogate;
5.完整實(shí)例:
using System.Collections.Generic;
using System.Text;
using System.IO.Compression;
using System.IO;
namespace Common
{
/// <summary>
/// 利用GzipStream進(jìn)行壓縮和解壓
/// </summary>
public class GZipUtil
{
private static GZipStream gZipStream = null;
/// <summary>
/// 壓縮
/// </summary>
/// <param name="srcBytes"></param>
/// <returns></returns>
public static byte[] Compress(byte[] srcBytes)
{
MemoryStream ms = new MemoryStream(srcBytes);
gZipStream = new GZipStream(ms, CompressionMode.Compress);
gZipStream.Write(srcBytes, 0, srcBytes.Length);
gZipStream.Close();
return ms.ToArray();
}
/// <summary>
/// 解壓
/// </summary>
/// <param name="srcBytes"></param>
/// <returns></returns>
public static byte[] Decompress(byte[] srcBytes)
{
MemoryStream srcMs = new MemoryStream(srcBytes);
gZipStream = new GZipStream(srcMs, CompressionMode.Decompress);
MemoryStream ms = new MemoryStream();
byte[] buffer = new byte[40960];
int n;
while ((n = gZipStream.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, n);
}
gZipStream.Close();
return ms.ToArray();
}
/// <summary>
/// 將指定的字節(jié)數(shù)組壓縮,并寫(xiě)入到目標(biāo)文件
/// </summary>
/// <param name="srcBuffer">指定的源字節(jié)數(shù)組</param>
/// <param name="destFile">指定的目標(biāo)文件</param>
public static void CompressData(byte[] srcBuffer, string destFile)
{
FileStream destStream = null;
GZipStream compressedStream = null;
try
{
//打開(kāi)文件流
destStream = new FileStream(destFile, FileMode.OpenOrCreate, FileAccess.Write);
//指定壓縮的目的流(這里是文件流)
compressedStream = new GZipStream(destStream, CompressionMode.Compress, true);
//往目的流中寫(xiě)數(shù)據(jù),而流將數(shù)據(jù)寫(xiě)到指定的文件
compressedStream.Write(srcBuffer, 0, srcBuffer.Length);
}
catch (Exception ex)
{
throw new Exception(String.Format("壓縮數(shù)據(jù)寫(xiě)入文件{0}時(shí)發(fā)生錯(cuò)誤", destFile), ex);
}
finally
{
// Make sure we allways close all streams
if (null != compressedStream)
{
compressedStream.Close();
compressedStream.Dispose();
}
if (null != destStream)
destStream.Close();
}
}
/// <summary>
/// 將指定的文件解壓,返回解壓后的數(shù)據(jù)
/// </summary>
/// <param name="srcFile">指定的源文件</param>
/// <returns>解壓后得到的數(shù)據(jù)</returns>
public static byte[] DecompressData(string srcFile)
{
if (false == File.Exists(srcFile))
throw new FileNotFoundException(String.Format("找不到指定的文件{0}", srcFile));
FileStream sourceStream = null;
GZipStream decompressedStream = null;
byte[] quartetBuffer = null;
try
{
sourceStream = new FileStream(srcFile, FileMode.Open, FileAccess.Read, FileShare.Read);
decompressedStream = new GZipStream(sourceStream, CompressionMode.Decompress, true);
// Read the footer to determine the length of the destiantion file
//GZIP文件格式說(shuō)明:
//10字節(jié)的頭,包含幻數(shù)、版本號(hào)以及時(shí)間戳
//可選的擴(kuò)展頭,如原文件名
//文件體,包括DEFLATE壓縮的數(shù)據(jù)
//8字節(jié)的尾注,包括CRC-32校驗(yàn)和以及未壓縮的原始數(shù)據(jù)長(zhǎng)度(4字節(jié)) 文件大小不超過(guò)4G
//為Data指定byte的長(zhǎng)度,故意開(kāi)大byte數(shù)據(jù)的范圍
//讀取未壓縮的原始數(shù)據(jù)長(zhǎng)度
quartetBuffer = new byte[4];
long position = sourceStream.Length - 4;
sourceStream.Position = position;
sourceStream.Read(quartetBuffer, 0, 4);
int checkLength = BitConverter.ToInt32(quartetBuffer, 0);
byte[] data;
if (checkLength <= sourceStream.Length)
{
data = new byte[Int16.MaxValue];
}
else
{
data = new byte[checkLength + 100];
}
//每100byte從解壓流中讀出數(shù)據(jù),并將讀出的數(shù)據(jù)Copy到Data byte[]中,這樣就完成了對(duì)數(shù)據(jù)的解壓
byte[] buffer = new byte[100];
sourceStream.Position = 0;
int offset = 0;
int total = 0;
while (true)
{
int bytesRead = decompressedStream.Read(buffer, 0, 100);
if (bytesRead == 0)
break;
buffer.CopyTo(data, offset);
offset += bytesRead;
total += bytesRead;
}
//剔除多余的byte
byte[] actualdata = new byte[total];
for (int i = 0; i < total; i++)
actualdata[i] = data[i];
return actualdata;
}
catch (Exception ex)
{
throw new Exception(String.Format("從文件{0}解壓數(shù)據(jù)時(shí)發(fā)生錯(cuò)誤", srcFile), ex);
}
finally
{
if (sourceStream != null)
sourceStream.Close();
if (decompressedStream != null)
decompressedStream.Close();
}
}
}
}
6.小結(jié)
進(jìn)行序列化,反序列化,利用到的都是BinaryFormate,都得借普通流MemoryStream,不同的是:
序列化時(shí),將對(duì)象序列化后放到MemoryStream,而反序列化時(shí),將MemoryStream中的byte[]數(shù)據(jù),反序列成對(duì)象
希望本文所述對(duì)大家的C#程序設(shè)計(jì)有所幫助。
相關(guān)文章
c# 動(dòng)態(tài)構(gòu)建LINQ查詢(xún)表達(dá)式
這篇文章主要介紹了c# 如何動(dòng)態(tài)構(gòu)建LINQ查詢(xún)表達(dá)式,幫助大家更好的理解和學(xué)習(xí)c#,感興趣的朋友可以了解下2020-11-11C#判斷指定驅(qū)動(dòng)器是否是Fat分區(qū)格式的方法
這篇文章主要介紹了C#判斷指定驅(qū)動(dòng)器是否是Fat分區(qū)格式的方法,涉及C#中DriveFormat屬性的使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04C#實(shí)現(xiàn)讀取指定盤(pán)符硬盤(pán)序列號(hào)的方法
這篇文章主要介紹了C#實(shí)現(xiàn)讀取指定盤(pán)符硬盤(pán)序列號(hào)的方法,涉及C#針對(duì)硬件屬性的相關(guān)操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2016-08-08C# SendInput 模擬鼠標(biāo)操作的實(shí)現(xiàn)方法
C# SendInput 模擬鼠標(biāo)操作的實(shí)現(xiàn)方法,需要的朋友可以參考一下2013-04-04DevExpress實(shí)現(xiàn)GridView當(dāng)無(wú)數(shù)據(jù)行時(shí)提示消息
這篇文章主要介紹了DevExpress實(shí)現(xiàn)GridView當(dāng)無(wú)數(shù)據(jù)行時(shí)提示消息,需要的朋友可以參考下2014-08-08Unity3D動(dòng)態(tài)對(duì)象優(yōu)化代碼分享
這篇文章主要介紹了Unity3D動(dòng)態(tài)對(duì)象優(yōu)化代碼分享的相關(guān)資料,需要的朋友可以參考下2015-03-03