0

ObjectOutputStream을 사용하여 HashTable<String,Object> 객체를 직렬화했습니다. 객체 직렬화 때, 나는 예외를 얻을 수 없지만, 직렬화시 다음과 같은 예외가 발생합니다 : 내가 아닌 값을 가지고있는 HashTable의 키를 모두 제거 할 때Java - 기본 유형을 포함하는 HashTable을 비 직렬화하는 중 오류가 발생했습니다

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

나는 더 이상 오류가 없습니다 String (내가 삭제 한 모든 키/값 쌍은 기본 값 유형을 값으로 가짐).

이 오류의 원인은 무엇입니까?

UPDATE는 - 여기에 내가 생각할 수있는 유일한 설명은 그 뭔가를 읽고 그것을 쓰는 당신 사이에 객체 스트림을 손상되는입니다 코드

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

답변

1

문제는 당신이 toString()를 사용하여 문자열을 바이트 배열 출력 스트림을 변환하고 있다는 점이다. toString() 메서드는 단순히 플랫폼 기본 인코딩을 사용하여 바이트 (문자를 전혀 나타내지 않지만 순전히 바이너리 데이터 임)를 String으로 변환하므로 손실이 발생하는 작업입니다. 이는 플랫폼 기본 인코딩 ing에는 가능한 모든 바이트에 유효한 문자가 없습니다.

바이너리 데이터를 저장하기 위해 String을 사용하지 않아야합니다. String에는 문자가 포함됩니다. String이 정말로 필요한 경우에는 16 진수 또는 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; 
} 
0

입니다. 의 소스 코드는 Java 1.0.2부터 변경되지 않았 음을 나타냅니다.

(로컬 클래스의 serialVersionID) (4290774380558885855)는 Java (tm)와 호환되도록 모든 Java 구현에서 표준입니다.

도움이 더 필요하면, 당신은 생성과 직렬화 된 객체의 읽기를 모두 커버하는 SSCCE를 제공해야합니다.

+0

코드와 함께 질문이 업데이트되었습니다. –