2014-05-21 2 views
1

내 Java 프로젝트에 문제가 있습니다. 여러 번 검색 한 후에도 계속 차단됩니다. ArrayList 확장 ListFromFile라는 이름의 클래스Java - "잘못된 스트림 헤더"ArrayList의 직렬화

내가 한 내 메인 클래스 BZ2MServer에서

public class ListFromFile<T> extends ArrayList<T> implements Serializable { 

    private String listFile; 

    public ListFromFile() { 
     this.listFile = null; 
    } 

    public ListFromFile(String file) { 
     this.listFile = file; 
    } 

    public void loadDataFromFile() { // Deserialize from file 

     try { 
      FileInputStream fileInput = new FileInputStream(this.listFile); 

      if (fileInput.read() == -1) { // If file is empty 
       this.saveDataInToFile(); 
      } else { 
       ObjectInputStream objectInput = new ObjectInputStream(fileInput); 

       this.addAll((ArrayList) objectInput.readObject()); 

       objectInput.close(); 
      } 

      fileInput.close(); 
     } catch (IOException | ClassNotFoundException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void saveDataInToFile() { // Serialize the ArrayList 
     try { 
      FileOutputStream fileOutput = new FileOutputStream(this.listFile, true); 
      ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput); 

      objectOutput.writeObject(this); 

      objectOutput.flush(); 
      objectOutput.close(); 
      fileOutput.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

} 

, 내가 ListFromFile으로 일부 개체를 만들었습니다

public class BZ2MServer { 

    private static ListFromFile<Specialite> specialites = new ListFromFile<Specialite>("liste_specialites.txt"); 
    private static ListFromFile<Module> modules = new ListFromFile<Module>("liste_modules.txt"); 
    private static ListFromFile<Professeur> professeurs = new ListFromFile<Professeur>("liste_professeurs.txt"); 
    private static ListFromFile<Etudiant> etudiants = new ListFromFile<Etudiant>("liste_etudiants.txt"); 
    private static ListFromFile<Note> notes = new ListFromFile<Note>("liste_notes.txt"); 

    public static void main(String[] args) { 
     specialites.loadDataFromFile(); 
    } 
} 

는 응용 프로그램이 시작될 때, 그것은로드 할 때 파일에 저장된 목록. 그게 내가 을 loadDataFromFile() 방법으로 실행하는 이유입니다. 이렇게하면 응용 프로그램을 처음 시작할 때 파일에 빈 ArrayList가 있어야합니다.

결과적으로 처음 출시 할 때 아무런 문제가 없습니다. 내가 BZ2MServer의 메인이 테스트 한

java.io.StreamCorruptedException: invalid stream header: ED000573 
    at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:804) 
    at java.io.ObjectInputStream.<init>(ObjectInputStream.java:299) 
    at bz2m.list.ListFromFile.loadDataFromFile(ListFromFile.java:31) 
    at bz2m.server.BZ2MServer.main(BZ2MServer.java:22) 

: 그러나,이 후, 난 항상 컴파일러에서이가 그런

public static void main(String[] args) { 
    Specialite test = new Specialite(1, "Test"); 

    specialites.add(test2); 

    specialites.saveDataInToFile(); 
} 

, 나는, 이전 코드를 제거를 얻을 수 LoadDataFromFile()을 사용 이전 데이터. 그리고 나는 그 오류를 얻었다. 그런 다음 ListFromFile 클래스에서 해당 조건을 제거했습니다.

if (fileInput.read() == -1) { 
    this.saveDataInToFile(); 
} 

그리고 작동했습니다. 그러나 파일이 비어있는 경우에는이 조건이 필요합니다. 파일이 없으면이 파일이 비어 있습니다.

java.io.EOFException 
    at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2325) 
    at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2794) 
    at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:801) 
    at java.io.ObjectInputStream.<init>(ObjectInputStream.java:299) 
    at bz2m.list.ListFromFile.loadDataFromFile(ListFromFile.java:31) 
    at bz2m.server.BZ2MServer.main(BZ2MServer.java:22) 

나는 당신이 내게 필요한 모든 정보를 제공해주기를 바랍니다. 필요한 경우 전체 프로젝트를 업로드 할 수 있습니다 (거대하지 않음).

감사합니다.

답변

4

사용중인 직렬화 방법에는 데이터 유효성을 확인하는 데 사용하는 magic number verification check이 포함되어 있습니다. 따라서 기대 한 것과 다른 것이라면 입력이 직렬화 표준을 따르지 않는다는 예외가 발생합니다.

이 경우 처음 두 바이트는 AC ED이고 그 뒤에 버전 00 05이 올 것으로 예상합니다. 당신은 상수 목록 here에서 그들을 볼 수 있습니다.

invalid stream header: ED000573은받은 입력의 처음 4 바이트가 ED 00 05 73임을 나타냅니다. 16 진수 뷰어에서 열면 실제로 혼란 스러울 수 있습니다. 위치 0에서 시작하는 첫 번째 바이트는 실제로 AC ED 00 05이므로 무엇이 문제입니까?

if (fileInput.read() == -1) { 
    this.saveDataInToFile(); 
} 

이 파일의 두 번째 바이트에 파일 포인터를 증가 한 바이트를 읽습니다

부하 방법이 실패하는 이유는 바로 그것 때문에 당신이 만든 확인이다. 이제 스트림을 ObjectInputStream로 전달하면 현재 포인터가있는 위치에서 처음 4 바이트를 읽게되고 ED 00 05 73을 참조한 다음 실패합니다. 뷰어에서 다음 바이트를보고이를 직접 확인할 수 있습니다.매우 감사합니다,

if (fileInput.getChannel().size() == 0) { 
    // empty file 
} 
+0

음 : 당신이 당신의 파일 대신 바이트 여부가 있는지 여부를 확인하는 바이트를 읽는, 비어 있지 여부를 확인하려면

, 단지 직접 길이 채널을 쿼리 많은 MxyL! 'fileInput.getChannel(). length'은 존재하지 않으므로'fileInput.getChannel(). size()'를 사용 했으므로 완벽하게 작동합니다 :) – WilliamZ

+0

'if (fileInput.available) == 0)'if (fileInput.getChannel(). size() == 0)'대신에? – WilliamZ

+0

죄송합니다. 'size()'가 아닌'length'입니다. 보통 두 개가 섞여 있습니다. 이 상황에서 '가능하다'는게 좋을 것입니다. 나는 단지 그것이 묘사에서 어떻게 들리는 지 정말로 좋아하지 않는다. – MxyL