DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

オブジェクトの内容をバイナリファイルに保存、復元する
オブジェクトのバイナリシリアル化、逆シリアル化を行う

オブジェクトの内容をバイナリファイルに保存する簡単な方法として、BinaryFormatterクラスを使う方法が挙げられます。BinaryFormatterを使用してオブジェクトをシリアル化し、FileStreamでファイルに書き込むのです。

補足:BinaryFormatterクラスの代わりにSoapFormatterクラスを使って、XMLファイルに保存することもできます。SoapFormatterの使い方は、ここで紹介している方法とほぼ同じです。

ここでは次のようなTestClassクラスがあるものとし、BinaryFormatterクラスを使ってTestClassオブジェクトをバイナリファイルに保存する方法を紹介します。

VB.NET
コードを隠すコードを選択
Public Class TestClass
    Private _message As String
    Private _number As Integer

    Public Property Message() As String
        Get
            Return _message
        End Get
        Set(ByVal Value As String)
            _message = value
        End Set
    End Property

    Public Property Number() As Integer
        Get
            Return _number
        End Get
        Set(ByVal Value As Integer)
            _number = value
        End Set
    End Property

    Public Sub New(ByVal str As String, ByVal num As Integer)
        _message = str
        _number = num
    End Sub
End Class
C#
コードを隠すコードを選択
public class TestClass
{
    private string _message;
    private int _number;

    public string Message
    {
        get {return _message;}
        set {_message = value;}
    }
    public int Number
    {
        get {return _number;}
        set {_number = value;}
    }

    public TestClass(string str, int num)
    {
        _message = str;
        _number = num;
    }
}

まず次のようにTestClassクラスにSerializableAttribute属性を付加する必要があります。

VB.NET
コードを隠すコードを選択
<Serializable()> _
Public Class TestClass
    '(省略)
End Class
C#
コードを隠すコードを選択
[Serializable()]
public class TestClass
{
    //(省略)
}

TestClassオブジェクトを保存、復元する具体的なコードを以下に示します。SaveToBinaryFileメソッドでオブジェクトを保存し、LoadFromBinaryFileメソッドでオブジェクトの復元ができます。

VB.NET
コードを隠すコードを選択
Imports System
Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary

Public Class MainClass
    Public Shared Sub Main()
        '保存先のファイル名
        Dim fileName As String = "C:\test.obj"

        'TestClassオブジェクトを作成
        Dim obj1 As New TestClass("テストです。", 123)

        'オブジェクトの内容をファイルに保存する
        SaveToBinaryFile(obj1, fileName)

        'オブジェクトの内容をファイルから読み込み復元する
        Dim obj2 As TestClass = CType(LoadFromBinaryFile(fileName), TestClass)

        '読み込んだオブジェクトの内容を表示
        Console.WriteLine(obj2.Message)
        Console.WriteLine(obj2.Number)

        Console.ReadLine()
    End Sub

    ''' <summary>
    ''' オブジェクトの内容をファイルから読み込み復元する
    ''' </summary>
    ''' <param name="path">読み込むファイル名</param>
    ''' <returns>復元されたオブジェクト</returns>
    Public Shared Function LoadFromBinaryFile(ByVal path As String) As Object
        Dim fs As New FileStream(path, FileMode.Open, FileAccess.Read)
        Dim f As New BinaryFormatter
        '読み込んで逆シリアル化する
        Dim obj As Object = f.Deserialize(fs)
        fs.Close()

        Return obj
    End Function

    ''' <summary>
    ''' オブジェクトの内容をファイルに保存する
    ''' </summary>
    ''' <param name="obj">保存するオブジェクト</param>
    ''' <param name="path">保存先のファイル名</param>
    Public Shared Sub SaveToBinaryFile( _
        ByVal obj As Object, ByVal path As String)
        Dim fs As New FileStream( _
            path, FileMode.Create, FileAccess.Write)
        Dim bf As New BinaryFormatter
        'シリアル化して書き込む
        bf.Serialize(fs, obj)
        fs.Close()
    End Sub
End Class
C#
コードを隠すコードを選択
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

public class MainClass
{
    public static void Main()
    {
        //保存先のファイル名
        string fileName = "C:\\test.obj";

        //TestClassオブジェクトを作成
        TestClass obj1 = new TestClass("テストです。", 123);

        //オブジェクトの内容をファイルに保存する
        SaveToBinaryFile(obj1, fileName);

        //オブジェクトの内容をファイルから読み込み復元する
        TestClass obj2 = (TestClass) LoadFromBinaryFile(fileName);

        //読み込んだオブジェクトの内容を表示
        Console.WriteLine(obj2.Message);
        Console.WriteLine(obj2.Number);

        Console.ReadLine();
    }

    /// <summary>
    /// オブジェクトの内容をファイルから読み込み復元する
    /// </summary>
    /// <param name="path">読み込むファイル名</param>
    /// <returns>復元されたオブジェクト</returns>
    public static object LoadFromBinaryFile(string path)
    {
        FileStream fs = new FileStream(path,
            FileMode.Open,
            FileAccess.Read);
        BinaryFormatter f = new BinaryFormatter();
        //読み込んで逆シリアル化する
        object obj = f.Deserialize(fs);
        fs.Close();

        return obj;
    }

    /// <summary>
    /// オブジェクトの内容をファイルに保存する
    /// </summary>
    /// <param name="obj">保存するオブジェクト</param>
    /// <param name="path">保存先のファイル名</param>
    public static void SaveToBinaryFile(object obj, string path)
    {
        FileStream fs = new FileStream(path,
            FileMode.Create,
            FileAccess.Write);
        BinaryFormatter bf = new BinaryFormatter();
        //シリアル化して書き込む
        bf.Serialize(fs, obj);
        fs.Close();
    }
}

保存しないフィールドを指定する

上記のようにBinaryFormatterを使用してオブジェクトを保存した場合、保存されるのはクラスのフィールドで、パブリックフィールドはもちろん、プライベートフィールドも保存されます。保存したくないフィールドにはNonSerializedAttribute属性を付けます。

次の例では、TestClassクラスの_numberフィールドをシリアル化の対象からはずし、保存されないようにしています。

VB.NET
コードを隠すコードを選択
<Serializable()> _
Public Class TestClass
    <NonSerialized()> _
    Private _message As String
    '(省略)
End Class
C#
コードを隠すコードを選択
[Serializable()]
public class TestClass
{
    private string _message;
    [NonSerialized()]
    private int _number;
    //(省略)
}
注意:「マイクロソフト サポート技術情報 - 320079」では「BUG: BinaryFormatter と .NET リモートが深いネスト Structs を deserialize することができません。」というバグが紹介されていますので、構造体のシリアル化でBinaryFormatterを使う場合は注意が必要です。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。