2017-04-16 145 views
0

我有一個應用程序以前通過序列化模型對象存儲了一些數據(QuickNote)。然後通過反序列化加載。如何將對象反序列化爲具有相同名稱的新對象?

不過,我更新的應用程序來存儲XML數據,而不是和我需要能夠導入舊的,序列化對象的轉換。新對象不是實現Serializable,雖然也有同名(QuickNote)。

我試圖反序列化老QuickNote和使用後續的代碼存儲到新的一個:

FileInputStream fileIn = new FileInputStream("data/quicknotes_user.dat"); 
ObjectInputStream in = new ObjectInputStream(fileIn); 
List<OldQuickNote> newList = (List<OldQuickNote>) in.readObject(); 

由於舊序列化文件中的類名是QuickNote,我得到的錯誤java.io.InvalidClassException: model.QuickNote; class invalid for deserialization因新的班級具有相同的名稱並且不執行Serializable

有沒有辦法來反序列化這個QuickNote對象爲OldQuickNote對象?無論QuickNoteOldQuickNote是相同的,只是QuickNote不再實行SerializableOldQuickNote一樣。

我的確嘗試尋找答案,但說實話,我甚至不知道如何搜索這個,因爲當我選擇首先序列化QuickNote對象時,我顯然做出了糟糕的設計決定。

注意事項:

  1. 我不能序列化對象改變對象類型(類名),因爲它是目前駐留在用戶的系統中。
  2. QuickNote對象不能改變,以實現Serializable,因爲它的註解和用於編組JAXB。
+0

最簡單的(只有?)解決方案是讓它再次實現'Serializable'。 – Henry

+0

我只是在我的問題中添加了一些警告。我不能用新對象實現'Serializable',因爲JAXB編組似乎不允許它使用'Serializable'對象。 – Zephyr

+0

歡迎來到Java對象序列化的世界 - 這些問題是我一般不推薦使用Java對象序列化的原因。 – Robert

回答

0

這在評論中得到了回答,但答案並未如此發佈。

我最終將舊類移動到不同的包中,並在用戶再次運行程序時轉換類。

我只需要等待我的用戶全部更新新版本並刪除舊版本。

謝謝!

1

在評論中提到了一個選項:強制將數據遷移到XML,然後擺脫舊的類。

另一種方法是嘗試分析它沒有Java序列機械的使用。有一些工具可以解析java序列化數據,例如https://github.com/gagern/nodeJavaDeserialization 雖然我在java中找不到任何庫,但是如果只有一個類數據要解析,解析它的任務看起來並不那麼可怕。該格式的文檔可用:http://docs.oracle.com/javase/6/docs/platform/serialization/spec/serialTOC.htmlObjectOutputStream/ObjectInputStream源也。

而且多了一個選擇是反序列化之前與序列化數據的發揮。想象一下,您將現有的QuickNote重命名爲QuickNot2(醜陋,但稍後有用),並將您的新課程重新創建爲QuickNote。然後,在反序列化QuickNot2之前,您將序列化的字節表示中的該e更改爲2。這是一個概念證明:

public class Data1 implements Serializable { 
    private final static long serialVersionUID = 123L; 

    private final String name; 

    public Data1(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 
} 

public class Data2 implements Serializable { 
    private final static long serialVersionUID = 123L; 

    private final String name; 

    public Data2(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 
} 

而且

Data1 data1 = new Data1("hello"); 

ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
ObjectOutputStream dos = new ObjectOutputStream(baos); 
dos.writeObject(data1); 
dos.close(); 
byte[] serialized = baos.toByteArray(); 

serialized[12] = '2'; 

ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(serialized)); 
Data2 data2 = (Data2) ois.readObject(); 
System.out.println(data2.getName()); 

此打印 '你好'。你可以看到,在這裏,我通過一個類序列化並通過另一個序列化,通過改變序列化形式的類的名稱(索引爲12的字節被更改,它存儲'1'的位置),反序列化。

對於這項工作,以下必須持有:

  1. 這兩個類(老QuickNoteQuickNot2必須具有相同的結構
  2. 他們都必須具有相同的serialVersionUID,所以如果不是你需要找到它並在你的代碼中指定它,爲了找到它,你可以在你的QuickNot2類中設置一些任意值,並查看由解串器產生的錯誤消息中的值。

QuickNot2建議離開班級名稱長度不變。看起來有可能完全改變這個類名,它的長度,我只是沒有檢查這個。

相關問題