0

我已经HashTable<String,Object>使用ObjectOutputStream. 序列化对象时,我没有得到任何异常,但是在反序列化时,会发生以下异常:

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

HashTable当我删除 中的所有键值不是 a时,我不再收到错误消息(我删除的所有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;
}
4

2 回答 2

1

问题是您正在使用toString(). 该toString()方法仅使用平台默认编码将字节(根本不代表字符,而是纯粹的二进制数据)转换为字符串。因此,这是一个有损操作,因为您的平台默认编码对于每个可能的字节都没有有效字符。

您不应该使用 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;
}
于 2013-07-28T07:33:04.940 回答
0

我能想到的唯一解释是,在您读取和写入对象流之间,某些东西正在破坏您的对象流。“本地类”(4290774380558885855) 中的 serialVersionID 是所有试图与 Java (tm) 兼容的 Java 实现的标准。源代码java.lang.Long表明该序列版本 ID 自 Java 1.0.2 以来没有改变。

如果您需要进一步的帮助,您需要提供一个涵盖序列化对象的创建和读取的 SSCCE。

于 2013-07-28T06:55:45.553 回答