C# 二進位制讀寫與序列化和反序列化
阿新 • • 發佈:2019-01-25
文章將實現資料儲存為二進位制檔案,然後通過二進位制檔案解析資料。
二進位制檔案讀寫操作:
//寫入二進位制檔案
public static void WriteByteValues()
{
string fileName = @"C:\Test.dat"
if (File.Exists(fileName))
File.Delete(fileName);
FileStream fs = new FileStream(fileName, FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(1.250F);
bw.Write(@"c:\Test");
bw.Write(10);
bw.Write(true);
bw.Close();
fs.Close();
}
//讀取二進位制檔案
public static void ReadByteValues()
{
if (File.Exists(fileName))
{
string fileName = @"C:\Test.dat"
FileStream fs = new FileStream(fileName, FileMode.Open);
BinaryReader br = new BinaryReader(fs);
Console.WriteLine(br.ReadSingle());
Console.WriteLine(br.ReadString());
Console.WriteLine(br.ReadInt32());
Console.WriteLine(br.ReadBoolean());
fs.Close();
br.Close();
}
}
測試:
static void Main(string[] args)
{
WriteByteValues();
ReadByteValues();
Console.ReadKey();
}
二進位制序列化和反序列化操作:
[Serializable]
public class Car
{
private Radio radio;
public string CarName { get; set; }
public string OwnerOfCar { get; set; }
}
[Serializable]
public class ChineseCar : Car
{
public int MaxSpeed { set; get; }
public bool CanFly { set; get; }
}
[Serializable]
public class Radio
{
[NonSerialized] public string radioID = "XF-552RR6";
public bool hasTweeters;
}
//序列化
public static void WriteSerializer(object obj, string filename)
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
using (FileStream fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write))
{
try
{
binaryFormatter.Serialize(fileStream, obj);
}
catch (Exception)
{
Console.WriteLine("fail");
throw;
}
}
}
//反序列化
public static void ReadDeSerializer(string filename)
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
using (FileStream fileStream = File.OpenRead(filename))
{
ChineseCar result = binaryFormatter.Deserialize(fileStream) as ChineseCar;
Console.WriteLine(result.CanFly);
Console.WriteLine(result.MaxSpeed);
Console.WriteLine(result.CarName);
Console.WriteLine(result.OwnerOfCar);
}
}
測試:
static void Main(string[] args)
{
ChineseCar myCar = new ChineseCar()
{
CanFly = false,
MaxSpeed = 200,
CarName = "Fly Man",
OwnerOfCar = "阿童木"
};
BeginChangeTObinary(myCar, fileName);
ShowBinaryFile(fileName);
Console.ReadKey();
}
上文中都是使用的是檔案流,資訊都會被寫在檔案中,產生額外的檔案。
接下來使用記憶體流,資訊都會被寫進記憶體中,不會產生額外的檔案。
二進位制記憶體流讀寫操作:
static void TestMemoryStream()
{
//如果使用檔案流,則資訊會被寫進檔案中
//而使用記憶體流,則資訊會被寫進記憶體中,不會產生額外的檔案
MemoryStream ms = new MemoryStream();
//將待寫入的資料從字串轉換為位元組陣列
byte[] testBytes = Encoding.UTF8.GetBytes("測試資料");
PrintInfo(ms);
ms.Write(testBytes, 0, testBytes.Length);
PrintInfo(ms);
//SeekOrigin的三種取值:
//1.Begin 指定流的開頭 2.Current 指定流內的當前位置 3.End 指定流的結尾
//將position重定位為開頭
ms.Seek(0, SeekOrigin.Begin);
byte[] bytes = new byte[testBytes.Length];
ms.Read(bytes, 0, bytes.Length);
Console.WriteLine("bytes:{0}", Encoding.UTF8.GetString(bytes, 0, bytes.Length));
PrintInfo(ms);
byte[] buffer = ms.GetBuffer();
Console.WriteLine("buffer:{0}", Encoding.UTF8.GetString(buffer, 0, buffer.Length));
PrintInfo(ms);
}
static void PrintInfo(MemoryStream ms)
{
Console.WriteLine("Capacity:{0}", ms.Capacity);
Console.WriteLine("Length:{0}", ms.Length);
Console.WriteLine("Position:{0}", ms.Position);
Console.WriteLine();
}
static void TestBinaryReaderWriter()
{
MemoryStream ms = new MemoryStream();
BinaryReader br = new BinaryReader(ms);
BinaryWriter bw = new BinaryWriter(ms);
bw.Write("helloworld");
ms.Seek(0, SeekOrigin.Begin);
string s = br.ReadString();
Console.WriteLine("content:{0}", s);
//字串的長度是可變的,因此無法確定字串的位元組數
//當使用BinaryWriter.Write寫入字串時,會用第一位來儲存字串的長度
ms.Seek(0, SeekOrigin.Begin);
byte[] bytes = ms.ToArray();
for (int i = 0; i < bytes.Length; i++)
{
Console.WriteLine("content1:{0}", bytes[i]);
}
}
二進位制記憶體流序列化和反序列化操作:
/// <summary>
/// 將物件序列化為byte[]
/// 使用IFormatter的Serialize序列化
/// </summary>
/// <param name="obj">需要序列化的物件</param>
/// <returns>序列化獲取的二進位制流</returns>
public static byte[] FormatterObjectBytes(object obj)
{
if (obj == null)
throw new ArgumentNullException("obj");
byte[] buff;
try
{
using (var ms = new MemoryStream())
{
IFormatter iFormatter = new BinaryFormatter();
iFormatter.Serialize(ms, obj);
buff = ms.GetBuffer();
Console.WriteLine("buff:{0}", Encoding.UTF8.GetString(buff, 0, buff.Length));
}
}
catch (Exception er)
{
throw new Exception(er.Message);
}
return buff;
}
/// <summary>
///將byte[]反序列化為物件
/// </summary>
/// <param name="buff"></param>
/// <returns></returns>
public static object FormatterByteObject(byte[] buff)
{
if (buff == null)
throw new ArgumentNullException("buff");
object obj;
try
{
using (var ms = new MemoryStream(buff))
{
IFormatter iFormatter = new BinaryFormatter();
obj = iFormatter.Deserialize(ms);
}
}
catch (Exception er)
{
throw new Exception(er.Message);
}
return obj;
}
測試:
static void Main(string[] args)
{
ChineseCar myCar = new ChineseCar()
{
CanFly = false,
MaxSpeed = 200,
CarName = "Fly Man",
OwnerOfCar = "阿童木"
};
OperatorByte.BeginChangeTObinary(myCar, fileName);
OperatorByte.ShowBinaryFile(fileName);
byte[] buff = OperatorByte.FormatterObjectBytes(myCar);
ChineseCar car = OperatorByte.FormatterByteObject(buff) as ChineseCar;
Console.WriteLine(car.CanFly);
Console.WriteLine(car.MaxSpeed);
Console.WriteLine(car.CarName);
Console.WriteLine(car.OwnerOfCar);
Console.ReadKey();
}
好了,祝進步。
每天進步一點點。