細 Wiki がページ「クラスの内容をバイナリファイルに保存または復元する」を「クラスの内容をバイナリファイルに保存または復元する(C Sharp)」に、リダイレクトを残さずに移動しま… |
細 文字列「</source>」を「</syntaxhighlight>」に置換 |
||
| (同じ利用者による、間の4版が非表示) | |||
| 1行目: | 1行目: | ||
== 概要 == | == 概要 == | ||
クラスの内容をバイナリファイルに保存する簡単な方法として、<code>BinaryFormatter</code>クラスを使う方法がある。<br> | |||
<code>BinaryFormatter</code>クラスを使用してクラスをシリアル化して、<code>FileStream</code>でファイルに書き込む。<br> | |||
<br> | <br> | ||
<code>BinaryFormatter</code>クラスの代わりに<code>SoapFormatter</code>クラスを使って、XMLファイルに保存することもできる。<br> | |||
<code>SoapFormatter</code>クラスの使い方は、ここで記載している方法とほぼ同様である。<br> | |||
<br><br> | <br><br> | ||
== | == バイナリファイル == | ||
==== シリアル化 ==== | |||
< | 以下に示すTestClassクラスを、<code>BinaryFormatter</code>クラスを使用してバイナリファイルに保存する。<br> | ||
<syntaxhighlight lang="c#"> | |||
public class TestClass | public class TestClass | ||
{ | { | ||
| 35行目: | 34行目: | ||
} | } | ||
} | } | ||
</ | </syntaxhighlight> | ||
<br> | <br> | ||
まず、以下のようにTestClassオブジェクトの先頭に<code>SerializableAttribute</code>属性を付加する。<br> | |||
< | <syntaxhighlight lang="c#"> | ||
[Serializable()] | [Serializable()] | ||
public class TestClass | public class TestClass | ||
{ | { | ||
// | // ...省略 | ||
} | } | ||
</ | </syntaxhighlight> | ||
<br> | <br> | ||
<code>SaveToBinaryFile</code>メソッドを使用して、バイナリファイルとしてシリアル化する。<br> | |||
また、<code>LoadFromBinaryFile</code>メソッドを使用して、バイナリファイルから逆シリアル化する。<br> | |||
< | <syntaxhighlight lang="c#"> | ||
using System; | using System; | ||
using System.IO; | using System.IO; | ||
| 107行目: | 106行目: | ||
} | } | ||
} | } | ||
</ | </syntaxhighlight> | ||
<br> | |||
==== シリアル化しないフィールドを指定する ==== | |||
上記のように、<code>BinaryFormatter</code>クラスを使用してシリアル化できるものは、クラスのフィールドである。<br> | |||
この時、publicフィールド、protectedフィールド、privateフィールドも保存される。<br> | |||
<br> | <br> | ||
保存しないフィールドには、<code>NonSerializedAttribute</code>属性を付加する。<br> | |||
<br> | <br> | ||
以下の例では、TestClassの_numberフィールドをシリアル化の対象から除外し、保存されないようにしている。<br> | |||
< | <syntaxhighlight lang="c#"> | ||
[Serializable()] | [Serializable()] | ||
public class TestClass | public class TestClass | ||
| 124行目: | 125行目: | ||
// (省略) | // (省略) | ||
} | } | ||
</ | </syntaxhighlight> | ||
<br><br> | |||
== XMLファイル == | |||
==== シリアル化できるもの ==== | |||
* 対象となるクラスの条件 | |||
** publicである | |||
**: publicではないクラスをシリアル化しようとすると、以下に示す<code>InvalidOperationException</code>例外が発生する。 | |||
**:<code>"保護レベルの設定が原因で 'ProjectName.ClassName' にアクセスできません。パブリックの型のみ処理できます。"</code> | |||
** publicな既定のコンストラクタを有する | |||
**: publicな既定のコンストラクタを持たないクラスをシリアル化しようとすると、以下に示す<code>InvalidOperationException</code>例外が発生する。 | |||
**: <code>"ProjectName.ClassName にはパラメーターを持たないコンストラクターが含まれていないため、これをシリアル化することはできません。"</code> | |||
*: <br> | |||
* 対象となる要素 | |||
** publicフィールド | |||
** getアクセサおよびsetアクセサを有するpublicプロパティ | |||
<br> | |||
==== XMLの書式の変更 ==== | |||
シリアル化の対象となるクラスおよびクラスのメンバに属性を付加することにより、保存するXMLファイルの書式を変更することができる。<br> | |||
<center> | |||
{| class="wikitable" style="background-color:#fefefe;" | |||
|+ XMLシリアル化を制御する属性 | |||
|- | |||
! style="background-color:#66CCFF;" | 属性 | |||
! style="background-color:#66CCFF;" | 機能 | |||
! style="background-color:#66CCFF;" | 適用前 | |||
! style="background-color:#66CCFF;" | 適用後 | |||
|- | |||
| XmlAttribute || メンバをXMLの属性とする || | |||
<syntaxhighlight lang="xml"> | |||
<ClassName> | |||
<field>256</field> | |||
</ClassName> | |||
</syntaxhighlight> | |||
| <syntaxhighlight lang="c++"><ClassName field="256" /></syntaxhighlight> | |||
|- | |||
| XmlArray || 配列の名前を変更する || | |||
<syntaxhighlight lang="xml"> | |||
<MemberName> | |||
<TypeName> | |||
<field>256</field> | |||
</TypeName> | |||
</MemberName> | |||
</syntaxhighlight> | |||
| <syntaxhighlight lang="xml"> | |||
<OriginalName> | |||
<TypeName> | |||
<field>256</field> | |||
</TypeName> | |||
</OriginalName> | |||
</syntaxhighlight> | |||
|- | |||
| XmlArrayItem || 配列の要素名を、型名から任意の名前に変更する。 || | |||
<syntaxhighlight lang="xml"> | |||
<MemberName> | |||
<TypeName> | |||
<field>256</field> | |||
</TypeName> | |||
</MemberName> | |||
</syntaxhighlight> | |||
| <syntaxhighlight lang="xml"> | |||
<MemberName> | |||
<OriginalName> | |||
<field>256</field> | |||
</TypeName> | |||
</MemberName> | |||
</syntaxhighlight> | |||
|} | |||
</center> | |||
<br> | |||
==== シリアル化 ==== | |||
以下のクラスを、XMLファイルに保存する手順を記載する。<br> | |||
<syntaxhighlight lang="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; | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
まず、次のようにTestClassオブジェクトに<code>SerializableAttribute</code>属性を付加する。<br> | |||
<syntaxhighlight lang="c#"> | |||
[Serializable()] | |||
public class TestClass | |||
{ | |||
// (省略) | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c#"> | |||
class Program | |||
{ | |||
static void Main() | |||
{ | |||
string fileName = "$HOME/Serialize.xml"; | |||
var myClass = new TestClass(); | |||
myClass.publicField = 1; | |||
myClass.Property = 2; | |||
using(var writer = new System.IO.StreamWriter(fileName)) | |||
{ | |||
// シリアル化の対象となるクラスの型を指定して XmlSerializerを作成する | |||
var serializer = new System.Xml.Serialization.XmlSerializer(typeof(TestClass)); | |||
// 指定のオブジェクトをシリアル化する | |||
serializer.Serialize(writer, TestClass); | |||
} | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
上記の例を実行する時、以下のようなXMLファイルが作成される。<br> | |||
<syntaxhighlight lang="xml"> | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<ClassName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> | |||
<publicField>1</publicField> | |||
<Property>2</Property> | |||
</ClassName> | |||
</syntaxhighlight> | |||
<br> | |||
上記の例では、<code>XmlSerializer</code>クラスのコンストラクタに<code>Type</code>クラスを指定しているが、これ以外にも下表に示すコンストラクタがある。<br> | |||
<center> | |||
{| class="wikitable" style="background-color:#fefefe;" | |||
|- | |||
! style="background-color:#66CCFF;" | XmlSerializerクラスのコンストラクタ | |||
|- | |||
| XmlSerializer(Type) | |||
|- | |||
| XmlSerializer(Type, String) | |||
|- | |||
| XmlSerializer(Type, Type[]) | |||
|- | |||
| XmlSerializer(Type, XmlAttributeOverrides) | |||
|- | |||
| XmlSerializer(Type, XmlAttributeOverrides, Type[], XmlRootAttribute, String) | |||
|- | |||
| XmlSerializer(Type, XmlAttributeOverrides, Type[], XmlRootAttribute, String, String) | |||
|- | |||
| XmlSerializer(Type, XmlRootAttribute) | |||
|- | |||
| XmlSerializer(XmlTypeMapping) | |||
|} | |||
[https://msdn.microsoft.com/ja-jp/library/system.xml.serialization.xmlserializer.aspx#Anchor_2 XmlSerializerクラス (System.Xml.Serialization) | MSDN]<br> | |||
</center> | |||
<br> | |||
<u>※注意</u><br> | |||
<u><code>XmlSerializer</code>クラスのインスタンスを生成する時、以下に示す<code>FileNotFoundException</code>例外が発生することがある。</u><br> | |||
<br> | |||
<u>これは、<code>XmlSerializer</code>クラスのアセンブリが用意されていないことが原因であり、sgen.exeファイルを実行して、このファイルを作成することで解決できる。</u><br> | |||
<u>もしくは、このファイルが存在しない場合は自動的に作成されるため、この例外を無視しても問題ない。</u><br> | |||
ファイルまたはアセンブリ 'mscorlib.XmlSerializers, Version=x.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'、またはその依存関係の 1 つが読み込めませんでした。指定されたファイルが見つかりません。 | |||
<br> | |||
==== 配列のシリアル化 ==== | |||
配列やListクラスの場合も、同様にシリアル化できる。<br> | |||
<syntaxhighlight lang="c#"> | |||
// int型配列 | |||
int[] array = new int[]{1, 2, 3}; | |||
var serializer = new XmlSerializer(typeof(int[])); | |||
// Listクラス | |||
List<int> list = new List<int>(new int[]{1, 2, 3}); | |||
var serializer = new XmlSerializer(typeof(List<int>)); | |||
</syntaxhighlight> | |||
<br> | |||
これらは、以下のように出力される。<br> | |||
<syntaxhighlight lang="xml"> | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<ArrayOfInt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> | |||
<int>1</int> | |||
<int>2</int> | |||
<int>3</int> | |||
</ArrayOfInt> | |||
</syntaxhighlight> | |||
<br> | |||
しかし、<code>ArrayList</code>クラスのような<code>Object</code>型を返すクラスでは型を特定できないため、以下に示す<code>InvalidOperationException</code>例外が発生する。<br> | |||
型 ProjectName.ClassName は指定されていません。スタティックに使用できない型を指定するには XmlInclude または SoapInclude 属性を使ってください。 | |||
<br> | |||
この場合、<code>XmlSerializer</code>クラスのコンストラクタにおいて、<code>Object</code>型に含まれる可能性のある型を全て指定する。<br> | |||
[https://msdn.microsoft.com/ja-jp/library/e5aakyae.aspx XmlSerializerクラスのコンストラクタ (Type, Type[<nowiki>]</nowiki>) (System.Xml.Serialization) | MSDN]<br> | |||
<syntaxhighlight lang="c#"> | |||
var obj = new ArrayList(new int[]{1, 2, 3}); | |||
var serializer = new XmlSerializer(typeof(ArrayList), new Type[]{typeof(int)}); | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="xml"> | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<ArrayOfAnyType xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> | |||
<anyType xsi:type="xsd:int">1</anyType> | |||
<anyType xsi:type="xsd:int">2</anyType> | |||
<anyType xsi:type="xsd:int">3</anyType> | |||
</ArrayOfAnyType> | |||
</syntaxhighlight> | |||
<br> | |||
==== 逆シリアル化 ==== | |||
作成されたXMLファイルは、逆シリアル化によりオブジェクトに復元できる。<br> | |||
<br> | |||
以下の例では、XMLファイルをストリームから読み込み、オブジェクトに変換している。<br> | |||
<br> | |||
<u>Windowsの場合、逆シリアル化を行うには、環境変数TEMPにより定義される一時フォルダに書き込むため、アクセス権が必要となる場合がある。</u><br> | |||
<syntaxhighlight lang="c#"> | |||
class Program | |||
{ | |||
static void Main() | |||
{ | |||
string fileName = "$HOME/Serialize.xml"; | |||
TestClass myClass; | |||
using(var reader = new System.IO.StreamReader(fileName)) | |||
{ | |||
var serializer = new System.Xml.Serialization.XmlSerializer(typeof(TestClass)); | |||
myClass = (TestClass)serializer.Deserialize(reader); | |||
} | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br><br> | <br><br> | ||
__FORCETOC__ | __FORCETOC__ | ||
[[カテゴリ:C_Sharp]] | [[カテゴリ:C_Sharp]] | ||