1. 程式人生 > >C# 二進位制讀寫與序列化和反序列化

C# 二進位制讀寫與序列化和反序列化

文章將實現資料儲存為二進位制檔案,然後通過二進位制檔案解析資料。

二進位制檔案讀寫操作:

        //寫入二進位制檔案
        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();
        }

好了,祝進步。

每天進步一點點。