簡體   English   中英

Java-將包含原始類型的HashTable反序列化時出錯

[英]Java - Error deserializing HashTable containing primitive type

我已經使用ObjectOutputStream序列化了HashTable<String,Object>對象。 序列化對象時,我沒有異常,但是反序列化時,會發生以下異常:

Exception in thread "main" java.io.InvalidClassException: java.lang.Long; local class
incompatible: stream classdesc serialVersionUID = 4290774032661291999, local class
serialVersionUID = 4290774380558885855

當我刪除HashTable中所有具有非String值的鍵時,不再收到錯誤(我刪除的所有鍵/值對都具有原始類型作為其值)。

是什么導致此錯誤?

更新-這是代碼

public static String serialize(Quiz quiz) throws IOException{
    HashMap<String,Object> quizData = new HashMap<String,Object>();
    quizData.put("version", 0); //int
    quizData.put("name", quiz.getName()); //String
    quizData.put("desc", quiz.getDesc()); //String
    quizData.put("timelimitType", quiz.getTimelimitType()); //String
    quizData.put("timelimit", quiz.getTimelimit()); //long
    ArrayList<String> serializedQuestionsData = new ArrayList<String>();
    for (Question question : quiz.getQuestions())
        serializedQuestionsData.add(Question.serialize(question));
    quizData.put("questions", serializedQuestionsData.toArray(new String[0])); //String[]
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos;
    try { oos = new ObjectOutputStream(baos); } catch (IOException error){ throw error; }
    try { oos.writeObject(quizData); } catch (IOException error){ throw error; }
    return baos.toString();
}
@SuppressWarnings("unchecked")
public static Quiz deserialize(String serializedQuizData) throws IOException, ClassNotFoundException{
    ByteArrayInputStream bais = new ByteArrayInputStream(serializedQuizData.getBytes());
    ObjectInputStream ois;
    try { ois = new ObjectInputStream(bais); } catch (IOException error){ throw error; }
    HashMap<String,Object> quizData;
    // Exception occurs on the following line!!
    try { quizData = (HashMap<String,Object>) ois.readObject(); } catch (ClassNotFoundException error){ throw error; }
    Quiz quiz;
    if ((int) quizData.get("version") == 0){
        quiz = new Quiz((String) quizData.get("name"),
                (String) quizData.get("desc"),
                (String) quizData.get("timelimitType"),
                (long) quizData.get("timelimit"));
        for (String serializedQuestionData : (String[]) quizData.get("questions"))
            quiz.addQuestion(Question.deserialize(serializedQuestionData));
    } else {
        throw new UnsupportedOperationException("Unsupported version: \"" + quizData.get("version") + "\"");
    }
    return quiz;
}

問題是您正在使用toString()將字節數組輸出流轉換為String。 toString()方法僅使用平台默認編碼將字節(根本不表示字符,而只是純二進制數據)轉換為String。 因此,這是有損操作,因為您的平台默認編碼對於每個可能的字節都沒有有效的字符。

您不應該使用String來保存二進制數據。 字符串包含字符。 如果您確實需要一個字符串,則使用十六進制或Base64編碼器對字節數組進行編碼。 否則,只需使用字節數組來保存您的二進制數據:

public static byte[] serialize(Quiz quiz) throws IOException{
    ...
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ...
    return baos.toByteArray();
}

@SuppressWarnings("unchecked")
public static Quiz deserialize(byte[] serializedQuizData) throws IOException, ClassNotFoundException{
    ByteArrayInputStream bais = new ByteArrayInputStream(serializedQuizData);
    ...
    return quiz;
}

我能想到的唯一解釋是,在您閱讀和編寫對象之間,某些東西正在破壞您的對象流。 在“本地類)(4290774380558885855)的serialVersionID在所有的Java實現,盡量與Java(TM)兼容的標准。對源代碼java.lang.Long說,該串行版本ID沒有因為Java 1.0中改變。 2。

如果您需要進一步的幫助,則需要提供一個SSCCE,其中涉及序列化對象的創建和讀取。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM