.net column
.NET開発者のためのブログメディア

C#におけるシリアライズ・デシリアライズの方法|Javaでの方法についても解説!

 
C#におけるシリアライズ・デシリアライズの方法|Javaでの方法についても解説!
基本情報技術者試験の試験対策はこちら>>
SE
XMLのシリアライズとは一体なんでしょうか?
PM
XMLファイルを作成することをシリアライズと呼びます。では詳しくみていきましょう。

目次

シリアライズ・デシリアライズとは?


今回はC#およびJavaにおけるシリアライズ・デシリアライズの方法を解説します。

まず、シリアライズとは何か説明します。シリアライズにはコンピュータ実行における意味とプログラミング言語における意味の2種類がありますが、今回は後者の解説となります。

なお、前者のコンピュータ実行における意味では「逐次化」と訳され、資源へのアクセス順序を調整することを指します。

プログラミング言語でのシリアライズ・デシリアライズ

では、プログラミング言語におけるシリアライズを説明します。

ここでのシリアライズは「直列化」と訳され、メインメモリ上に存在しているオブジェクトなどのデータを文字列やバイト列に変換することを指します。これには、ファイルとして保存したり、ネットワークで送受信したりできるようになるというメリットがあります。

逆に、シリアライズされたデータをもとの状態に復元することをデシリアライズと言います。

C#におけるXMLのシリアライズ・デシリアライズとは?

現在のソフトウェア開発において、XMLファイルは多くのシステムで使用されています。XMLファイルを作成することをシリアライズ、XMLファイルを読み込むことをデシリアライズと言います。C#でそれを行うにはどうしたら良いのでしょうか。

この記事ではまずXMLとは何か、という基本的なところから、C#でXMLをシリアライズ・デシリアライズする方法をわかりやすく解説します。XML初心者の方は是非ご覧ください。

C#でシリアライズ・デシリアライズに活用されるXMLとは

XMLとは以下のように<と>を使用したテキストファイルのフォーマットのことです。<と>の部分はタグと言います。Webページを記述する時に使うHTMLに似ています。

Javaにおけるオブジェクトのシリアライズ・デシリアライズとは?

Javaでは専用のオブジェクト直列化ストリームプロトコルに従って、オブジェクトをシリアライズできます。こちらはC#のようなXML形式のテキストデータではなくバイナリデータで出力されます。テキストエディタ等でファイルの内容を見ても人間が理解できる形にはなっていません。

C#におけるXMLのシリアライズ・デシリアライズのやり方

では、C#でのシリアライズおよびデシリアライズのやり方をサンプルコードとともに解説していきます。ファイルが生成されることで実感もわきますので、是非実際に動かして確認してみてください。

C#におけるXMLのシリアライズのやり方2つ

以下のC#のサンプルは、上のラーメンのXMLをシリアライズします。

1:属性でタグの名前を指定できる

上のC#のサンプルを順に説明しましょう。まず、RamenとGuというクラスを定義しています。[XmlRoot(“~”)]と[XmlElement(“~”)]という属性を記述していますが、これによりXMLにシリアライズした時のタグの名前を指定できます。

属性で指定しない場合は、クラス名のRamenやプロパティ名のMenがそのまま使われます。ただしXMLのタグ名は先頭が小文字なことが通例なので、このように属性を使って変更しているのです。

2:XmlSerializerでシリアライズする

Mainメソッドでは、まずRamenクラスを生成しています。この時コンストラクタが呼ばれてRamen内部のGuのインスタンスも生成されます。

そしてMenなどのプロパティに文字列を代入しています。次にXmlSerializerクラスをRamenクラスを指定して生成し、using内でファイル書き込みを行うStreamWriterを生成します。StreamWriterの引数にはファイル名・追記するかどうか=false・文字エンコード=UTF8を指定しています。

usingを使用して安全にシリアライズできる

usingは{と}で囲った処理が終わった後に、後始末してくれるC#の機能です。このようなファイル制御で使用すればファイルのclose処理を自動的に行ってくれます。

{と}の中では、XmlSerializerに生成したRamenクラスとStreamWriterクラスを渡して、Serializeでシリアライズを行います。このC#サンプルを実行すればCドライブのtestフォルダにramen.xmlが作成されます。

C#におけるXMLのデシリアライズのやり方5つ

次は、C#でXMLファイルをデシリアライズする(読み込む)方法を説明します。ここまでのC#サンプルの、Mainメソッドを以下のように書き換えましょう。

1:XmlReaderでデシリアライズできる

上のC#サンプルを実行すると、以下のように表示されます。

XmlSerializer・StreamReader・XmlReaderを使用することでramen.xmlをデシリアライズして、Ramenクラスのインスタンスとして読み込めていることがわかります。

2:XMLElementクラスでシリアライズ

ここまでのC#サンプルのRamenクラスのような、独自のクラスを作らずにXMLをシリアライズする場合はどうすればよいのでしょうか。その場合はXMLElementが便利です。Mainメソッドを以下のように書き換えてください。また「using System.Xml;」の追加も必要となります。

3:AppendChildメソッドで追加が可能

上を実行するとramen.xmlファイルが生成されます。その中身は以下のようになります。

XmlElementのAppendChildメソッドでXMLのツリー構造が実現できています。

4:XmlElementにデシリアライズ

XMLファイルをXmlElementの型にデシリアライズすることもできます。サンプルのMainメソッドを以下のように書き換えてください。

5:独自クラスを使わずデシリアライズできる

上のサンプルを実行すると、

と表示されます。XmlElement型のインスタンスとして取りこめていることがわかります。

Javaオブジェクトのシリアライズ・デシリアライズのやり方

ここまで、C#におけるシリアライズとデシリアライズのやり方を紹介してきました。
ですが、Javaにおいても同様にオブジェクトの内容をファイル出力する方法があります。
ここからは、Javaにおけるシリアライズとデシリアライズを紹介します。

クラスにSerializableインターフェイスを実装する

まずは、シリアライズしたいクラスの実装方法を紹介します。
以下はC#サンプルのRamenクラスとGuクラスをJavaで実装した場合の例となります。

上の例では、シリアライズするオブジェクトであるRamenとGuというクラスにはSerializableインターフェイスを実装しています。シリアライズによってストリームに書き込めるオブジェクトはSerializableインターフェイスをサポートするものだけです。

なお、Serializableにメソッドおよびフィールドはなく、直列化可能であるという意味を識別する機能だけを備えています。

ObjectOutputStream・ObjectInputStreamを用いる

シリアライズでオブジェクトをファイル出力する場合、ObjectOutputStreamを使用します。これによって作成されたファイルをデシリアライズで読み込む場合、ObjectInputStreamを使用します。

ObjectOutputStreamによるシリアライズ

では、実際にJavaでのシリアライズ例を見ていきましょう。

上の例では、まずRamenクラスを生成しています。この時コンストラクタが呼ばれてRamen内部のGuのインスタンスも生成されます。

そしてMenなどのプロパティに文字列を代入しています。次に、try-with-resources文でファイル書き込みを行うObjectOutputStreamを生成します。その後、writeObjectメソッドでRamenオブジェクトの内容をシリアライズして出力します。

ObjectInputStreamによるデシリアライズ

次は、Javaをデシリアライズする(読み込む)方法を説明します。ここまでのサンプルの、Mainクラスを以下のように書き換えましょう。

上のC#サンプルを実行すると、以下のように表示されます。

これでファイルをデシリアライズして、Ramenクラスのインスタンスとして読み込めていることがわかります。

Javaでシリアライズ・デシリアライズする時の注意点

Javaでのシリアライズおよびデシリアライズのやり方を解説してきました。ただし、Javaでのデシリアライズでは制約事項となる注意点があります。それらについて、ここで紹介します。

対象オブジェクトの定義がないとエラーになる

上の例において、RamenクラスをRamen2クラスに名前変更して実行すると「java.lang.ClassNotFoundException:」というエラーが発生します。これは、シリアライズしたオブジェクトのクラスが存在しないことを示します。

また、GuクラスをGu2クラスに名前変更して実行してみましょう。すると、「java.io.InvalidClassException:」というエラーとなります。これは、シリアライズしたオブジェクトのクラスになんらかの不具合があったことを示します。RamenクラスでGuが見つからないことでこのようなエラーとなっています。

オブジェクトの定義内容を変更するとメソッドの定義までは復元不可

例のGuクラスにあるgetEggメソッドをmeatが戻り値となるよう変更して実行すると、結果は以下のようになります。

Guのオブジェクト内容は読み込めていますが、メソッド定義が変わったことで実行結果が変わってしまいます。このように、クラスの定義を変更すると結果が復元できなくなる場合があります。

SE
HTMLに似ていますが、もっと効率的な方法なんですね。
PM
その分奥の深い仕様ですが是非マスターして活用していきましょう。

C#のシリアライズでXMLを活用しよう

この記事でC#のXMLの扱いの基礎が理解できたのではないでしょうか。XMLには色々な仕様があり奥が深いですが、その分覚えれば大きく差がつきます。是非マスターしてXMLを活用してください。

C#やJavaでのシリアライズ・デシリアライズの方法を知ろう

この記事でC#におけるXML扱いの基礎が理解できたのではないでしょうか。XMLには色々な仕様があり奥が深いですが、その分覚えれば大きく差がつきます。是非マスターしてXMLを活用してください。

また、Javaにおけるシリアライズとデシリアライズの方法も紹介しました。是非マスターして活用してください。


.NET分野でのキャリアアップをお考えの方は、現在募集中の求人情報をご覧ください。

また、直接のエントリーも受け付けております。

エントリー(応募フォーム)

Search

Popular

reccomended

Categories

Tags