1

I have a trouble with my java project. After several searches, i'm still blocked.

I have a class named ListFromFile that extends ArrayList :

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

}

In my main class BZ2MServer, i've created some objects with 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();
    }
}

When the application starts, it loads the lists saved in files. That's why i execute saveDataInToFile() inside that loadDataFromFile() method. By this way, the files should contain empty ArrayList at the first time we launch the application.

The result is that for the first launch, there is no issue. However, after this, i always have this from the compiler :

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)

I have tested this in the main of BZ2MServer:

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

    specialites.add(test2);

    specialites.saveDataInToFile();
}

Then, i removed the previous code, used LoadDataFromFile() to get the previous datas. And i got the error. Then, i removed that condition in ListFromFile class :

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

And it worked. However, that condition was necessary in the case the file is empty. Without it, and if the file is empty, i get this :

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)

I hope that i have give you all the information you need to help me. If you need, i can upload the entire project (not huge).

Thank you !

0

1 Answer 1

4

The serialization methods you're using includes a magic number verification check that it uses to determine whether your data is valid or not. So if it's anything other than what it expects, it will throw an exception telling you that your input does not conform to its serialization standards.

In this case, it expects the first two bytes to be AC ED followed by a version 00 05. You can see them in the list of constants here.

The invalid stream header: ED000573 indicates that the first 4 bytes of the input that it received is ED 00 05 73. If you open it in a hex viewer, you might actually be confused: the first bytes starting at position 0 is indeed AC ED 00 05, so what's the problem?

The reason why your load method fails is precisely because of that check you made:

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

This reads one byte, which increments the file pointer to the second byte in the file. Now when you pass your stream to the ObjectInputStream for loading, it will read the first 4 bytes from where the current pointer is, see ED 00 05 73 and then fail. You can verify this yourself by looking at the next byte after in your viewer.

If you want to check whether your file is not empty, instead of reading a byte to check whether there are bytes or not, just query the channel for its length directly:

if (fileInput.getChannel().size() == 0) {
    // empty file
}
Sign up to request clarification or add additional context in comments.

3 Comments

Well, thank you very much MxyL ! fileInput.getChannel().length doesn't exist, so i used fileInput.getChannel().size(), then it works perfectly :)
Is it bad to use if ( fileInput.available() == 0 ) instead of if ( fileInput.getChannel().size() == 0 ) ?
Oops it is size() not length I usually get those two mixed up. available in this situation should be fine. I just don't really like how it sounds from the description.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.