2012-07-10 52 views
1

我正在使用以下代碼來保存和檢索Android和內部存儲器中的對象。我用一個成功的字符串對象測試了它。當我嘗試保存位圖時,出現IOException。 (我發現我必須調用compress方法)所以我注意到我可以保存一些對象,保存對象有什麼限制?某些對象不保存到Android內部存儲器

當我保存一個對象時,它只保存字段嗎?我可以保存包含其他對象的對象嗎?請清除我。

代碼:

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); 

     } 

    } 

在此先感謝。

回答

1

限制是所有對象都必須是可序列化的(實現Serializable接口)。如果一個對象的對象數據成員不是序列化的,它必須被標記爲瞬態:

private transient SomeClass notSerializable; 

編輯有關序列化不可序列成員

這取決於你正在試圖序列,是不是有什麼序列化。由於這是一個用Android標記的問題,因此它可能是一個Context對象。

由於很好的原因,上下文不可序列化,它們與應用程序或Activity的生命週期相關聯。它的狀態是不穩定的,即使你稍後可以序列化和反序列化它,它的內部狀態也是沒有意義的,因爲新的上下文已經建立,現在可能正在運行一個新的線程或甚至不同的進程。

如果數據成員喜歡上下文,則需要將它們聲明爲瞬態並將新的有效當前上下文重新分配給反序列化的對象。

如果你試圖序列不同種類的,一方面只是代表像一串字符串和/或數字的數據對象,但另一方面不序列化,你有兩個選擇:

  • 如果這些是你的類,然後只需添加Serializable接口給他們
  • 或者你可以自定義你的類序列化過程中具有不可序列數據成員

定製可以通過實現我做thods

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

這些方法在類的序列化/反序列化時被調用。訣竅是獲取不可序列化的對象的數據/狀態,並將該數據打包爲可序列化的對象。例如,您可以使用像ArrayList這樣的任何Collection對象來順序存儲原始數據。

讓我們假設你想序列化一個Location對象(對於地理位置座標),讓我們也假定該對象是不可序列化的。但是,你知道,它是由可序列化的三個值:

  • 雙經度
  • 雙緯度
  • 雙海拔
  • (以及其他類似提供商,速度,時間...)

您可以將這三個值存儲在一個ArrayList中,或者您可以創建自己的自定義的可序列化類,以存儲用於序列化目的的這些值。 將ArrayList或您的可序列化中間對象放入您的自定義writeObject方法的ObjectOutputStream中。

在readObject中,您需要反轉這些步驟並根據您序列化的原始數據重建不可序列化的數據成員。

我還建議您閱讀Sun的documentation about serialization

+0

當我加載對象時,將標記爲瞬態的對象設置爲null? – 2012-07-10 15:42:57

+0

是的,因爲在Java中沒有其他方式來表達未定義的狀態 – tiguchi 2012-07-10 15:51:33

+0

有沒有辦法保存瞬態數據類型? – 2012-07-10 16:37:36

0

是的,你可以保存所有類型的數據的一個對象,你只需要確保您要定義對象中的所有變量:

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

您還需要確保您使用的是一套方法,掀起那些對象的字段:

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

}

} 

如果您未明確設置字段,將無法保存它們。

+0

因此,我可以保存一個包含位圖對象的對象,但我無法自行保存位圖對象(使用上面提供的代碼)? – 2012-07-10 15:34:31

+0

你能提供你的對象類的代碼,以及你用來調用'writeObject'方法的代碼嗎? – BlackHatSamurai 2012-07-10 16:22:59

0

從Oracle的Javadoc:

一個ObjectOutputStream寫入雙方的基本數據類型和圖形 Java對象到底層OutputStream。然後可以使用ObjectInputStream讀取(重構)對象和其他數據 。 對象的持久存儲可以通過使用流的文件來完成。如果該流是網絡套接字流,則可以在另一個主機或另一個進程中重建對象 。

只有支持java.io.Serializable或 java.io.Externalizable接口的對象可以被串行化爲輸出 流。每個可序列化對象的類都被編碼,包括該類的類名稱和簽名,該對象的非靜態和非瞬態字段和數組的值,以及該對象引用的其他對象的值(除了那些不要 本身實現java.io.Serializable接口)。多個 對同一對象的引用使用引用共享 機制進行編碼,以便可以適當地恢復對象的圖形 。

對象的默認序列化機制將寫入類 的對象,類簽名以及所有非瞬態 和非靜態字段的值。對其他對象的引用( 瞬態或靜態字段除外)也會導致寫入這些對象。

相關問題