[C#] シリアライズ(Serialization)をする方法


Devlopment note / C#    作成日付 : 2020/04/30 19:32:04   修正日付 : 2020/04/30 19:32:04

こんにちは。明月です。


この投稿はC#でシリアライズ(Serialization)をする方法に関する説明です。


シリアライズとはメモリに割り当てしているクラスのデータをバイナリ化することです。つまり、クラス内部で変数のデータをすべてbyteタイプに変換することだと思えば良いです。

シリアライズは昔にたくさん使った記憶がありますが、最近はシリアライズよりJsonタイプに変換してデータ化することがトレンドなので、最近はよく使わないみたいです。

link - [C#] Newtonsoft.JSONライブラリを利用してJsonデータ構造を扱う方法


でも、Newtonsoft.Jsonを利用してデータをJsonタイプに変換することはクラスのPublicタイプだけ変換するし、データをすべてStringタイプに変換するので、限界があります。

シリアライズはPublicデータだけではなく、Privateも構造化するし、クラス自体をすべてByteタイプに変換することなので、クラス自体を格納することではよいです。


でも、シリアライズも短所があります。バイナリ化するので、当該なデータを人が読みにくいです。なのでメモ帳でデータ変更ができないです。

また、クラス自体を変換しましたから、クラスが変更がある場合に復元ができない可能性もあります。

Jsonも場合はプログラム言語に関係しずに、読み込む移植性がよいですが、シリアライズはC#で作成したらC#しか読み込まれないです。


正確にはクラス変更や他のプレートフォームでも読み込まられないことではないですが、データ漏れが発生したり、データが可笑しくなる可能性があります。

つまり、バグ発生する可能性があることです。


仕様によってシリアライズがよいかJsonを使うかを正しく選択して使う方がよいです。

using System;
using System.IO;
// シリアライズのライブラリ
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace Example
{
  // シリアライズを使うために、当該クラスのアトリビュートに宣言する。
  [Serializable]
  // テストクラス
  class Node
  {
    // 変数 - データ格納はコンストラクタで出力はPrint関数だけ。
    private string data;
    // コンストラクタ
    public Node(string data)
    {
      this.data = data;
    }
    // 出力関数
    public void Print()
    {
      // コンソールに出力
      Console.WriteLine(this.data);
    }
  }
  class Program
  {
    // 実行関数
    static void Main(string[] args)
    {
      // テストクラスを宣言
      // node.dataには「Test」データが格納される
      var node = new Node("Test");

      // シリアライズフォーマットクラス
      var formatter = new BinaryFormatter();
      // クラスをシリアライズして格納する変数
      byte[] data;
      // Streamでシリアライズしてdata変数にデータをコピーする。
      using (var stream = new MemoryStream())
      {
        // クラスをStreamタイプに変換
        formatter.Serialize(stream, node);
        // 変数のサイズを割り当てする。
        data = new byte[stream.Length];
        // Streamのデータをbyteタイプに変換
        data = stream.GetBuffer();
      }
      // シリアライズしたデータをファイルに格納する。
      using (var stream = new FileStream("c:\\work\\Serializable.dat", FileMode.Create, FileAccess.Write))
      {
        stream.Write(data, 0, data.Length);
      }

      // データを読み込む
      var info = new FileInfo("c:\\work\\Serializable.dat");
      // データを再割り当てする。
      data = new byte[info.Length];
      // ファイルからデータを読み込む。
      using (var stream = info.OpenRead())
      {
        stream.Read(data, 0, data.Length);
      }

      // Streamでデータをデシリアライズする。
      using (MemoryStream stream = new MemoryStream())
      {
        // byteをStreamに読み込む。
        stream.Write(data, 0, data.Length);
        // Stream seekを最初に移動する。
        stream.Seek(0, SeekOrigin.Begin);
        // クラスをデシリアライズしてNodeクラスにキャストする。
        node = (Node)formatter.Deserialize(stream);
      }
      // データを出力する。
      node.Print();

      Console.WriteLine("Press any key...");
      Console.ReadKey();
    }
  }
}

Nodeというクラスをシリアライズしてbyte[]タイプに変換しました。変換してファイルに格納します。

また、格納したファイルを読み込んでデシリアライズでbyte[]データをクラスタイプに変換します。


ファイルをメモ帳で開きました。


人が解析することでは無理があります。


ここまでC#でシリアライズ(Serialization)をする方法に関する説明でした。


ご不明なところや間違いところがあればコメントしてください。

最新投稿