MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
C Sharpの基礎 - シリアライズのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
C Sharpの基礎 - シリアライズ
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == クラスの内容をバイナリファイルに保存する簡単な方法として、<code>BinaryFormatter</code>クラスを使う方法がある。<br> <code>BinaryFormatter</code>クラスを使用してクラスをシリアル化して、<code>FileStream</code>でファイルに書き込む。<br> <br> <code>BinaryFormatter</code>クラスの代わりに<code>SoapFormatter</code>クラスを使って、XMLファイルに保存することもできる。<br> <code>SoapFormatter</code>クラスの使い方は、ここで記載している方法とほぼ同様である。<br> <br><br> == バイナリファイル == ==== シリアル化 ==== 以下に示すTestClassクラスを、<code>BinaryFormatter</code>クラスを使用してバイナリファイルに保存する。<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> <code>SaveToBinaryFile</code>メソッドを使用して、バイナリファイルとしてシリアル化する。<br> また、<code>LoadFromBinaryFile</code>メソッドを使用して、バイナリファイルから逆シリアル化する。<br> <syntaxhighlight lang="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(); } } </syntaxhighlight> <br> ==== シリアル化しないフィールドを指定する ==== 上記のように、<code>BinaryFormatter</code>クラスを使用してシリアル化できるものは、クラスのフィールドである。<br> この時、publicフィールド、protectedフィールド、privateフィールドも保存される。<br> <br> 保存しないフィールドには、<code>NonSerializedAttribute</code>属性を付加する。<br> <br> 以下の例では、TestClassの_numberフィールドをシリアル化の対象から除外し、保存されないようにしている。<br> <syntaxhighlight lang="c#"> [Serializable()] public class TestClass { private string _message; [NonSerialized()] private int _number; // (省略) } </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> __FORCETOC__ [[カテゴリ:C_Sharp]]
C Sharpの基礎 - シリアライズ
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse