Write specific line into file
Question
I'm trying to write line into a file at line-position n.
Even if line n isn't present. In that case the file has to grow with empty lines to reach n. Basically something like writer.writeLine(n, mycontent)
. mycontent is a binary representation from ObjectOutputStream
. Each line of the file contains a serialized object. The line-number is the index.
How can I write to a specific line? - Without using FileUtils or any non-standard API components.
This answer pretty much sums up what I want - but with writing it seems to behave different.
edit: I clarified my question due to the comments
Solution
Is the notion of line is very important to you? Otherwise you could probably serialize a Map in a file, and use it to write or read your objects at a specific index (in that case, the index would be key of the map).
Here's a little example.
public static void main(String[] args) throws Exception {
ObjectOutputStream tocStream = new ObjectOutputStream(new FileOutputStream("myfile.toc"));
Map<Integer,Object> tableOfContent = new HashMap<Integer, Object>();
String myString = "dataOne";
Date myDate = new Date();
tableOfContent.put(0,myDate);
tableOfContent.put(1,myString);
tocStream.writeObject(tableOfContent);
tocStream.flush();
tocStream.close();
ObjectInputStream tocInputStream = new ObjectInputStream(new FileInputStream("myfile.toc"));
Map<Integer,Object> restoredTableOfContent = (Map<Integer, Object>) tocInputStream.readObject();
Object restoredMyString = restoredTableOfContent.get(1);
System.out.println(restoredMyString);
tocInputStream.close();
}
OTHER TIPS
This won't work, because each serialized object might contain one or several newline character(s) as part of the its binary representation. So if you write a new object at line 3, you might very well write the object in the middle of the binary representation of your first one. Test it :
public class OOSTest {
public static void main(String[] args) throws IOException {
String s = "Hello\nWorld";
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(s);
oos.flush();
oos.close();
System.out.println(new String(bos.toByteArray()));
}
}
IMHO, you have three choices:
- Choose a protocol which will work with binary data (for example: for each object, write its length (in bytes) as an integer (4 bytes) followed with the bytes of the object itself;
- Encode the serialized bytes into a string, using Base64 for example, and use a separator between the objects which is not part of the encoding;
- Use an ObjectOutputStream to serialize an array of Objects. Writing a new entry would consist in deserializing the array, make sure it has the right size or copy it to a new array of the appropriate size, insert your object at its position, and reserialize the whole array.
- Loop through the file reading the current values.
- Write each value out to a new temp file.
- If the old file ends before your line number keep writing out blank lines.
- Then once you get to the line number you want to update write out the new data.
- If there is more lines to the old file keep writing.
- Delete the old file. Rename the temp file.