2009年6月10日水曜日

Java XMLEncoder、XMLDecoderを使用したオブジェクトの保存(シリアライズ/デシリアライズ)その1

オブジェクトの状態をXMLファイルに保存(シリアライズ)したり、XMLファイルかデータを読み込みオブジェクトを復元(デシリアライズ)したりするには
java.beans.XMLEncoderクラスとjava.beans.XMLDecorderクラスを使用します。
※Javaではシリアライズ/デシリアライズを行うためにjava.io.ObjectOutputStream とjava.io.ObjectInputStreamを使用してバイナリファイルに読み書きを行っていたらしいのですが、色々問題があったようでJDK 1.4からシリアライズの新たな機能としてXMLファイルにオブジェクトの状態を読み書きするjava.beans.XMLEncoder、java.beans.XMLDecoderクラスが追加されたそうです。



まずはFrameに配置したTextAreaの状態(入力内容や色、フォントなど)をXMLファイルに読み書きします。

package FileAccess;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class SerializableSample01 extends Frame implements ActionListener{

private static final long serialVersionUID = 1L;

public static void main(String args[]){
new SerializableSample01();
}

Button btnSave;
Button btnLoad;
TextArea ta;

public SerializableSample01(){
this.setTitle("SerializableSample01");
this.setSize(300, 300);

ta = new TextArea();
this.add(ta,BorderLayout.CENTER);

Panel p1 = new Panel();
btnSave = new Button("Save");
btnSave.addActionListener(this);
btnLoad = new Button("Load");
btnLoad.addActionListener(this);
p1.add(btnSave);
p1.add(btnLoad);
this.add(p1,BorderLayout.SOUTH);

this.setVisible(true);
}


public void actionPerformed(ActionEvent arg0) {
if (arg0.getSource() == btnSave){
save();
}else if (arg0.getSource() == btnLoad){
load();
}
}

/*
* テキストエリアの状態をXMLファイルに書き込みます。
*/
private void save(){
FileOutputStream fos = null;
BufferedOutputStream bos = null;
XMLEncoder encoder = null;

try {
fos = new FileOutputStream("D:/SerializableSample01.xml");
bos = new BufferedOutputStream(fos);
encoder = new XMLEncoder(bos);

encoder.writeObject(ta);

} catch (FileNotFoundException e) {
e.printStackTrace();
} finally { 
if (encoder != null){
encoder.close();
}
}

//テキストエリアを削除します。
this.remove(ta);
ta = null;
this.validate();   
}

/*
* テキストエリアの状態をXMLファイルから読み取ります。
*/
private void load(){
FileInputStream fis = null;
BufferedInputStream bis = null;
XMLDecoder decoder = null;

try {
fis = new FileInputStream("D:/SerializableSample01.xml");
bis = new BufferedInputStream(fis);
decoder = new XMLDecoder(bis);

ta = (TextArea)decoder.readObject();

} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (decoder != null){ 
decoder.close();
}
}

//テキストエリアを追加します。
this.add(ta,BorderLayout.CENTER);
this.validate();
}

}


まずテキストエリアに書き込みます。


saveボタンでテキストエリアの状態をシリアライズして、フレームからテキストエリアを削除します。


loadボタンでテキストエリアの状態を復元し、フレームに追加します。



テキストエリアの状態を保存したXMLファイルの内容です。
 
 
 
 
 
255 
255 
255 
255 
 
 
 
28 
 
 
text0 
 
 
28 
 
 
28 
 
 
シリアライズ

デシリアライズ

サンプルです。 
 
 
 


XMLEncoderクラス、XMLDecoderクラスで読み書きできるオブジェクト



XMLEncoderクラス、XMLDecoderクラスで読み書きできるオブジェクトは
デフォルトコントラスタが必ずあること。
インスタンス変数にアクセスするためのアクセッサが定義されていること。
アクセッサの名前はset変数名、get変数名(booleanを返す場合is変数名でもOK)であること。



簡単なクラスを作成し、そのオブジェクトをXMLEncoderクラス、XMLDecoderクラスで読み書きしてみます。


名前と年齢をフィールドに持つEmployeeクラス
package FileAccess;

public class Employee {
private String _name;
private int _age;

public Employee(){
_name = "No Name";
_age = 0;
}

public Employee(String name, int age){
_name = name;
_age = age;
}

public void setName(String value){ _name = value; }
public String getName(){ return _name; }

public void setAge(int value){ _age = value; }
public int getAge(){ return _age; }

}


EmployeeクラスをXMLに書き込み、再度そのXMLを読み込みEmployeeクラスを復元して名前と年齢をコンソールに出力します。
package FileAccess;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

public class SerializableSample02 {

public static void main(String args[]){

Employee emp = new Employee("yan",25);

FileOutputStream fos = null;
BufferedOutputStream bos = null;
XMLEncoder enc = null;
try {
fos = new FileOutputStream("D:/Employee.xml");
bos = new BufferedOutputStream(fos);
enc = new XMLEncoder(bos);

enc.writeObject(emp);
enc.flush();

} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (enc != null){
enc.close();
}
}

FileInputStream fis = null;
BufferedInputStream bis = null;
XMLDecoder dec = null;

try {
fis = new FileInputStream("D:/Employee.xml");
bis = new BufferedInputStream(fis);
dec = new XMLDecoder(bis);

Employee newEmp = (Employee)dec.readObject();

System.out.println(newEmp.getName());
System.out.println(newEmp.getAge());

} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (dec != null){
dec.close();
}
}
}
}

0 件のコメント: