Marek Marek - 6 months ago 15
Java Question

Write and read multiple objects to file

I am designing an handwriting application for android.

I would like to write information (

class LogInfo
) into a log file, every time the user presses the enter button.

After that, I would like to read the stored information.

This is part of my class with a custom write method:

public class LogInfo implements Serializable {

private static final long serialVersionUID = -5777674941129067422L;

public static List<Point[][]> strokes;
public static List<byte[]> codes;

// Only write and read methods shown

private void writeObject(ObjectOutputStream stream) throws IOException
{
stream.defaultWriteObject();
stream.writeInt(strokes.size());
Point[][] pointsArray = null;
for (int i = 0; i < strokes.size(); i++)
{
pointsArray = ((Point[][])strokes.get(i));
stream.writeInt(pointsArray.length);
for (int j = 0; j < pointsArray.length; j++)
{
stream.writeInt(pointsArray[j].length);
for (int k = 0; k < pointsArray[j].length; k++)
{
stream.writeInt(pointsArray[j][k].x);
stream.writeInt(pointsArray[j][k].y);
//stream.writeObject(elementData[i]);
}
}
}

int size = codes.size();
stream.writeInt(size);
for (int i = 0; i < size; i++)
{
stream.write(codes.get(i));
}
}


This is the read method:

private void readObject(java.io.ObjectInputStream stream)
{
stream.defaultReadObject();
int strokesSize = stream.readInt();
for (int i = 0; i < strokesSize; i++)
{
int arrayXSize = stream.readInt();
Point[][] points = new Point[arrayXSize][];
for (int j = 0; j < arrayXSize; j++)
{
int arrayYSize = stream.readInt();
points[j] = new Point[arrayYSize];
for (int k = 0; k < arrayYSize; k++)
points[j][k] = new Point(stream.readInt(), stream.readInt());
}
strokes.add(points);
}

int codesSize = stream.readInt();
for (int i = 0; i < codesSize; i++)
{
byte[] buffer = new byte[3];
stream.read(buffer, 0, 3);
codes.add(buffer);
}
}


It works well when I save only one object in the file. When I try to save more, reading is not working (it throws a
StreamCorruptedException
). It reads only one object in the while loop!

In the main class, I just use two simple methods:

// WRITE TO FILE
logInfo.writeLog();

// READ FROM FILE
ArrayList<LogInfo> logInfoArrayList = logInfo.readLog();


defined as:

public void writeLog()
{
File file = new File (Environment.getExternalStorageDirectory().getAbsolutePath(), "data.log");
FileOutputStream fos;
try {
fos = new FileOutputStream(file, true);
//fos = openFileOutput(Environment.getExternalStorageDirectory().getAbsolutePath() + "/data.log", Context.MODE_APPEND);
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(this);
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public ArrayList<LogInfo> readLog()
{
ArrayList<LogInfo> logInfoArray = new ArrayList<LogInfo>();

try{
File file = new File (Environment.getExternalStorageDirectory().getAbsolutePath(), "data.log");
FileInputStream fis = new FileInputStream(file);
ObjectInputStream reader = new ObjectInputStream(fis);

LogInfo tempLogInfo = new LogInfo();
while((tempLogInfo = (LogInfo)reader.readObject()) != null)
logInfoArray.add(tempLogInfo);
reader.close();
} catch (Exception e) {
//TODO Auto-generated catch block
e.printStackTrace();
}

return logInfoArray;
}


requested UPDATE:

//We use this class to not write a header in a file that already exist
class MyObjectOutputStream extends ObjectOutputStream {

public MyObjectOutputStream(OutputStream os) throws IOException {
super(os);
}

@Override
protected void writeStreamHeader() {}
}

EJP EJP
Answer
  1. You can't append to an existing file created with an ObjectOutputStream, at least not without effort. There is a trick somewhere about extending ObjectOutputStream and overriding the writeStreamHeader() method so as not to write the stream header the second time, but I'm not in favour of it. You should really rewrite the whole file, maybe as a List.

  2. You don't need all this code. Just make strokes and codes non-static and non-transient, and get rid of the readObject() and writeObject() methods altogether.

Comments