1

次のコードを使用して、Androidの内部メモリとの間でオブジェクトを保存および取得しています。文字列オブジェクトでテストして成功しました。ビットマップを保存しようとすると、IOExceptionが発生します。(compressメソッドを呼び出さなければならないことがわかりました)それで、いくつかのオブジェクトを保存できることに気付きました。オブジェクトを保存する際の制限は何ですか?

オブジェクトを保存すると、フィールドのみが保存されますか?他のオブジェクトを含むオブジェクトを保存できますか?片付けてください。

コード:

    public Object readObjectFromMemory(String filename) {
        Object defautObject = null;
        FileInputStream fis;
        try {
            fis = game.openFileInput(filename);
            ObjectInputStream is = new ObjectInputStream(fis);
            defautObject = is.readObject();
            is.close();
            this.gameEngineLog.d(classTAG, "Object successfully read: " + filename);
        } 
        catch (FileNotFoundException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "FileNotFoundException");
            this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename);

        } 
        catch (StreamCorruptedException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "StreamCorruptedException");
            this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename);

        } 
        catch (IOException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "IOException");
            this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename);

        } 
        catch (ClassNotFoundException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "ClassNotFoundException");
            this.gameEngineLog.d(classTAG, "Object couldn't be opened: " + filename);

        }

        return defautObject;

    }

public void writeObjectToMemory(String filename, Object object) {
        FileOutputStream fos;
        try {
            fos = game.openFileOutput(filename, Context.MODE_PRIVATE);
            ObjectOutputStream os = new ObjectOutputStream(fos);
            os.writeObject(object);
            os.close();
            this.gameEngineLog.d(classTAG, "Object successfully written: " + filename);
        } 
        catch (FileNotFoundException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "Object couldn't be written: " + filename);

        } 
        catch (IOException e) {
            e.printStackTrace();
            this.gameEngineLog.d(classTAG, "Object couldn't be written: " + filename);

        }

    }

前もって感謝します。

4

3 に答える 3

1

制限は、すべてのオブジェクトがシリアライズ可能でなければならない (インターフェース Serializable を実装する) ことです。オブジェクトのオブジェクト データ メンバーがシリアライズ可能でない場合は、一時的なものとしてマークする必要があります。

private transient SomeClass notSerializable;

シリアル化できないメンバーのシリアル化に関する編集

シリアル化できないものをシリアル化しようとしていることに依存します。これは Android でタグ付けされた質問なので、たとえば Context オブジェクトである可能性があります。

コンテキストは正当な理由でシリアル化できません。アプリケーションまたはアクティビティのいずれかのライフサイクルに関連付けられています。その状態は揮発性であり、後でシリアル化および逆シリアル化できたとしても、新しいコンテキストが確立され、新しいスレッドまたは別のプロセスが実行されている可能性があるため、内部状態は意味をなさないでしょう。

コンテキストのようなデータ メンバーの場合、それらを一時的として宣言し、デシリアライズされたオブジェクトに新鮮で有効な現在のコンテキストを再割り当てする必要があります。

一方では一連の文字列や数値などのデータを表すだけで、他方ではシリアライズ可能ではないさまざまな種類のオブジェクトをシリアライズしようとしている場合は、次の 2 つのオプションがあります。

  • これらがクラスである場合は、それらに Serializable インターフェイスを追加するだけです
  • または、シリアル化できないデータ メンバーを持つクラスでシリアル化プロセスをカスタマイズできます。

メソッドを実装することでカスタマイズ可能

private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;

これらのメソッドは、クラスのシリアル化/逆シリアル化で呼び出されます。秘訣は、シリアル化できないオブジェクトのデータ/状態を取得し、代わりにそのデータをシリアル化可能なオブジェクトにパックすることです。たとえば、ArrayList のような任意の Collection オブジェクトを使用して、生データを順次格納できます。

Location オブジェクトを (地理的位置座標用に) シリアライズする必要があり、オブジェクトがシリアライズ可能ではないと仮定します。しかし、シリアル化できる 3 つの値で構成されていることがわかります。

  • 二重経度
  • 二重緯度
  • 二重高度
  • (およびプロバイダー、速度、時間などの他のもの...)

これらの 3 つの値を ArrayList に格納するか、シリアル化の目的でこれらの値を格納する独自のカスタムのシリアル化可能なクラスを作成することができます。ArrayList またはシリアライズ可能な中間オブジェクトをカスタム writeObject メソッドの ObjectOutputStream に入れます。

readObject では、これらの手順を逆にして、シリアル化した生データに基づいてシリアル化できないデータ メンバーを再構築する必要があります。

また、シリアライゼーションに関するSun のドキュメントを読むことをお勧めします。

于 2012-07-10T15:27:21.890 に答える
0

はい、オブジェクト内のすべてのタイプのデータを保存できます。オブジェクト内のすべての変数を定義していることを確認する必要があります。

public class YourObject{
int yourInteger;
String yourString;
Bitmap yourBitmap;
float yourFloat;
...
}

set メソッドを使用して、これらのオブジェクトからフィールドを設定していることも確認する必要があります。

public class YourObject{
int yourInteger;
String yourString;
Bitmap yourBitmap;
float yourFloat;
...
//sets the value of yourInt
public void setYourInteger(int yourInt){
 this.yourInt = yourInt;

}

}

フィールドを明示的に設定しないと、フィールドを保存できません。

于 2012-07-10T15:29:53.037 に答える
0

Oracle の Javadoc から:

ObjectOutputStream は、プリミティブ データ型と Java オブジェクトのグラフの両方を基になる OutputStream に書き込みます。オブジェクトとその他のデータは、ObjectInputStream を使用して読み取る (再構成する) ことができます。オブジェクトの永続ストレージは、ストリーム用のファイルを使用して実現できます。ストリームがネットワーク ソケット ストリームの場合、オブジェクトは別のホストまたは別のプロセスで再構成できます。

出力ストリームに直列化できるのは、java.io.Serializable または java.io.Externalizable インターフェースをサポートするオブジェクトだけです。各直列化可能オブジェクトのクラスは、クラス名とクラスのシグネチャ、オブジェクトの非静的および非一時的なフィールドと配列の値、およびオブジェクトによって参照されるその他のオブジェクト (実装されていないものを除く) を含めてエンコードされます。 java.io.Serializable インターフェイス自体)。同じオブジェクトへの複数の参照は、参照共有メカニズムを使用してエンコードされるため、オブジェクトのグラフを適切に復元できます。

オブジェクトのデフォルトのシリアライゼーション メカニズムは、オブジェクトのクラス、クラス シグネチャ、すべての非一時的および非静的フィールドの値を書き込みます。他のオブジェクトへの参照 (一時フィールドまたは静的フィールドを除く) により、それらのオブジェクトも書き込まれます。

于 2012-07-10T15:30:53.643 に答える