Issue
I have a problem with reading objects from file. When I'm trying to read objects from .dat file, it's only printing the first one object. Then an error message will appear 'java.io.StreamCorruptedException: invalid type code: AC'. What is wrong with my code? I have tried to find a solution without succees. Every object is saved individually to the file (I have save button in my GUI).
my object saving method which parameter is object:
public static void saveObject(GymDiary object){
try (ObjectOutputStream dataOut = new ObjectOutputStream(new FileOutputStream("objectFile.dat", true))){
dataOut.writeObject(object);
dataOut.flush();
dataOut.close();
System.out.println("saving succeeded!");
} catch (IOException e) {
e.printStackTrace();
}
}
my object reading method:
public static void readObjects() throws IOException {
ArrayList<gymDiary> objectList = new ArrayList<>();
boolean endOfFile= true;
int x = 0;
try (ObjectInputStream objectFile = new ObjectInputStream(new FileInputStream("objectFile.dat"))) {
while (endOfFile) {
gymDiary object = null;
try {
object = (GymDiary) objectFile.readObject();
objectList.add(object);
} catch (ClassNotFoundException e){
e.printStackTrace();
}
if (object != null) {
System.out.println(objectList.get(x).getLoad());
x++;
} else {
endOfFile= false;
objectFile.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Error joins the line: object = (GymDiary) objectFile.readObject();
Is something wrong in that method where I save objects? Or is the problem in my saving method? or both? :D
My goal is print all objects that are in my file. Not only the first.
.dat file looks like this with 2 objects (some stuff in my mother language, do not mind):
¬í sr *com.example.work.gymDiaryËQj$b8ˆ L kuormatt Ljava/util/ArrayList;L
liikeNimetq ~ L toistotq ~ L treeninNimit Ljava/lang/String;xpsr java.util.ArrayListxÒ™Ça I sizexp w sr java.lang.Double€³ÂJ)kû D valuexr java.lang.Number†¬•”à‹ xp@I sq ~ @I sq ~ @I xsq ~ w t squatxsq ~ w sr java.lang.Integerâ ¤÷‡8 I valuexq ~ q ~ q ~ xt legday¬í sr *com.example.work.gymDiaryËQj$b8ˆ L kuormatt Ljava/util/ArrayList;L
liikeNimetq ~ L toistotq ~ L treeninNimit Ljava/lang/String;xpsr java.util.ArrayListxÒ™Ça I sizexp w sr java.lang.Double€³ÂJ)kû D valuexr java.lang.Number†¬•”à‹ xp@I sq ~ @I sq ~ @I xsq ~ w t
benchpressxsq ~ w sr java.lang.Integerâ ¤÷‡8 I valuexq ~ q ~ q ~ xt upperbodyday
Solution
The problem here is most likely that your serialization and deserialization methods behave differently. Your serialization code always creates a new ObjectOutputStream
and then appends the data to the file. This will write the stream header (magic & version) every time. However your deserialization method only creates an ObjectInputStream
once, and therefore also only consumes the stream header once. Therefore you either have to:
- use a single
ObjectOutputStream
to write all objects - or use a separate new
ObjectInputStream
to read each object
Additionally your logic for detecting the end of file might be flawed (unless there is code you omitted). When there is no further object in the stream, readObject()
throws an exception (currently EOFException
, but this specific exception is not guaranteed by the documentation). Therefore you should explicitly call writeObject(null)
; then you can detect when readObject()
returns null
and consider that the end of your data.
It might also be good to consider alternatives to Java serialization, because it is in some cases not very efficient, and for untrusted data it can be pretty dangerous, leading to remote code execution in the worst case (protections against this are verbose and error-prone). See also Secure Coding Guidelines for Java SE.
Answered By - Marcono1234
Answer Checked By - Marilyn (JavaFixing Volunteer)