手っ取り早くクラスをファイルにシリアライズするための基底クラス

　クラスにファイル保存機能をつける基底クラスです。
　クラスのインスタンスをシリアライズ・デシリアライズする処理を共通化するために作成しました。

　クラスのメンバー変数をそのままファイルに保存出来ますので非常にお手軽に利用できます。

　ファイルはアプリのローカルファイルに保存されます。
　Android以外で使用する場合は、FileOutputStream,FileInputStream生成部を変更してください。

# ソース
```java:FileSerializableBase.java

import android.content.Context;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;


/**
 * ファイルへシリアライズ出来るクラスの基底クラス
 * このクラスを派生することで簡単にシリアライズされるクラスを作れる
 * @author F/T
 *
 */
public class FileSerializableBase implements Serializable {
	private static final long serialVersionUID = 1L;

    ////////////////////////////////////////////////////////////////////////////////
    // ■ フィールド
    ////////////////////////////////////////////////////////////////////////////////

	// システム
	public int  _serialize_savecount_ = 0;										// セーブ回数
	transient String _serialize_filename_;										// ファイル名  ※保存はされない

	// ※ 派生クラスでシリアライズするフィールドを記述


    ////////////////////////////////////////////////////////////////////////////////
    // ■ 永続化
    ////////////////////////////////////////////////////////////////////////////////

	/**
	 * シリアライズしてファイルに保存
	 * @param context	コンテキスト
	 * @return	true:保存成功 false:保存失敗
	 */
	public boolean save(Context context) {
		_serialize_savecount_++;
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;
		try {
		    fos = context.openFileOutput(_serialize_filename_, Context.MODE_PRIVATE);
		    oos = new ObjectOutputStream(fos);
		    oos.writeObject(this);
		} catch (Exception ex) {
			ex.printStackTrace();
			return false;
		}finally{
			try {
				if ( oos!=null ) oos.close();
				if ( fos!=null ) fos.close();
			}catch(IOException ex ) {
				ex.printStackTrace();
				return false;
			}
		}
		return true;
	}

	/**
	 * ファイルからデシリアライズしてインスタンス生成
	 * ※ファイルが存在シない場合は、初期値でインスタンスを生成
	 * @param context	コンテキスト
	 * @param clazz	インスタンスを生成するクラス
	 * @param filename ファイルネーム
	 * @return 生成されたインスタンス
	 */
	static public FileSerializableBase newInstance(Context context , Class clazz , String filename) {
		FileSerializableBase instance = null;	// 生成するインスタンス

		FileInputStream fis = null;
		ObjectInputStream ois = null;
		try {
		    fis = context.openFileInput(filename);
		    ois = new ObjectInputStream(fis);
		    instance = (FileSerializableBase) ois.readObject();
		} catch (Exception ex) {
		}finally{
			try {
				if ( ois!=null ) ois.close();
				if ( fis!=null ) fis.close();
			}catch(IOException ex ) {
				ex.printStackTrace();
			}
		}

		if ( instance  ==null ) {
			// instanceがnullの場合は新規作成する
			try {
				instance = (FileSerializableBase)clazz.newInstance();
			} catch (InstantiationException e) {
				e.printStackTrace();
				return null;
			} catch (IllegalAccessException e) {
				e.printStackTrace();
				return null;
			}
		}
		instance._serialize_filename_ = filename;

		instance.loadAfter();	    // メンバー 新規作成分の初期化

		return instance;
	}


    /**
     * デシリアライズ後の初期化
     * ※メンバーを新規作成した場合に、未初期化のメンバーを初期化する
     */
	public void loadAfter() {
	}

    ////////////////////////////////////////////////////////////////////////////////
    // ■ ファイル操作
    ////////////////////////////////////////////////////////////////////////////////

	/**
	// ファイル削除
	 * @param context	コンテキスト
	 */
	public void delete(Context context) {
		context.deleteFile(_serialize_filename_);
	}
}
```


# 利用例
## 派生クラス
ここではゲームで使用することを想定して「PlayInfo」というクラスを作成します。
プレイヤー名、ハイスコアリスト、音量設定を保持します。

```java:PlayInfo.java
import android.content.Context;
import FileSerializableBase;

public class PlayInfo extends FileSerializableBase {
	private static final long serialVersionUID = 1L;

	////////////////////////////////////////////////////////////
	// インスタンス生成
	static public PlayInfo newInstance(Context context  ) {
		return newInstance(context,  "playinfo.dat");
	}
	static public PlayInfo newInstance(Context context , String filename ) {
		return (PlayInfo)FileSerializableBase.newInstance(context, PlayInfo.class , filename);
	}

	////////////////////////////////////////////////////////////
	// プレイ中の選択状態

	public String playerName="AAA"; // プレイヤー名
	public ArrayList<Integer> highScores; // ハイスコアリスト
	public int soundVolume=100; // 音量設定

	@Override
	public void loadAfter() {
		if ( highScores == null ) highScores = new ArrayList<Integer>();
	}
}


```

## クラスの利用例1
以下の処理を行っています。
+ インスタンス生成（保存済みのファイルを読み込み）
+ プレイヤー名を設定
+ ハイスコアリストにスコアの追加
+ 保存

```java
// インスタンス生成・読み込み（保存済みならでファイルからデシリアライズ）
PlayInfo playinfo = PlayInfo.newInstance(getApplicationContext());
// 値設定
playinfo.playerName="eternal force blizzard";
playinfo.highScores.add(new Integer(4321));
// 保存（シリアライズ）
playinfo.save(getApplicationContext());

```

## クラスの利用例2
以下の処理を行っています。
+ インスタンス生成（保存済みのファイルを読み込み）
+ 音量設定
+ 保存

```java
// インスタンス生成・読み込み（保存済みならでファイルからデシリアライズ）
// ファイル名を指定(setting.dat)
PlayInfo playinfo = PlayInfo.newInstance(getApplicationContext(),"setting.dat");
// 値設定
soundVolume = 77;
// 保存（シリアライズ）
// ※保存先のファイル名はインスタンス生成時のファイル名が使用される
playinfo.save(getApplicationContext());

```


# 解説
PlayInfoクラスでは２つのインスタンス生成メソッドを作成しています。

## インスタンス生成
基底クラスのインスタンス生成メソッドを呼び出しています。
その際に、Context,PlayInfo自身のクラス、ファイル名を指定しています。
※ PlayInfo自身のクラスは、デシリアライズ時のクラス生成に使用します。

```java
	static public PlayInfo newInstance(Context context , String filename ) {
		return (PlayInfo)FileSerializableBase.newInstance(context, PlayInfo.class , filename);
	}
```


必要に応じてファイル名が省略された場合、デフォルトのファイル名を指定する生成メソッドも用意します。
設定ファイルの場合、ファイル名が固定になるのでクラスで指定しておいたほうが便利でしょう。

```java
	static public PlayInfo newInstance(Context context  ) {
		return newInstance(context,  "playinfo.dat");
	}
```


## メンバー変数

メンバー変数がそのまま保存されます。
※ シリアライズ可能なクラスである必要があります。

```java
	public String playerName="AAA"; // プレイヤー名
	public ArrayList<Integer> highScores; // ハイスコアリスト
	public int soundVolume=100; // 音量設定
```

以下のメンバー変数が規定クラス側で自動的に追加されます。
値は保存するごとに加算されます。
```java
	public int  _serialize_savecount_ = 0;										// セーブ回数
```

## 保存（シリアライズ）
save()メソッドを呼ぶことで、保存されます。
ファイル名はインスタンス生成時に指定したものが使用されます。

## メンバー変数追加時の処理
メンバー変数は後から追加することも出来ます。
既に保存されていたファイルを読み込んだ場合は、初期値になります。
インスタンスがnullのままでは困るメンバー変数については、loadAfter()メソッド内で初期化してください。
loadAfter()メソッドはnewInstance内でデシリアライズの後に呼ばれます。

```java
	@Override
	public void loadAfter() {
		if ( highScores == null ) highScores = new ArrayList<Integer>();
	}
```

## ファイルの削除
インスタンスを生成した状態で、delete() メソッドを呼んでください。