2

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

Community
  • 1
  • 1
wishi
  • 7,188
  • 17
  • 64
  • 103
  • BufferedWriter wrapped into an ObjectOutputStream? Can you clarify this a bit? – Hovercraft Full Of Eels Jan 15 '11 at 13:49
  • 2
    Your question is very unclear. ObjectOutputStream will write binary data - there's no such concept as a "line" in ObjectOutputStream. – Jon Skeet Jan 15 '11 at 13:49
  • Sorry, I updated my question. I use the line-number as an index to lookup serialized objects again from a "container" file. The problem is that if the line-number is the index, I have to be able to chose where to write within the file. And I don't want to cache it entirely. – wishi Jan 15 '11 at 13:56

3 Answers3

2

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:

  1. 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;
  2. 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;
  3. 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.
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • which still doesn't clarify how I can write at a specific line position... It seems to get very complex. – wishi Jan 15 '11 at 14:54
2

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();
}
Tony
  • 1,214
  • 14
  • 18
  • I wanted to avoid to have to rewrite. Seems to be impossible... I'm not sure how to realize updates on that file containing serialized objects. It may grow large. Still I think this is leading the way. Thanks. – wishi Jan 15 '11 at 19:47
0
  • 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.
jzd
  • 23,473
  • 9
  • 54
  • 76
  • is that really necessary? I don't want to rewrite everything just because of one change. – wishi Jan 15 '11 at 14:06
  • Yes. That is why a database or some other structure to store your data might be a better choice. – jzd Jan 15 '11 at 14:09
  • any simple suggestions? I have no experience with this and I don't want to run into too much complexity. – wishi Jan 15 '11 at 15:15
  • 1
    A database would be a better choice but does add complexity. If this is the only data you are storing, I would just use this file and rebuild it each time you need to save data. As long as the file is not super huge this should not be a be performance issue. – jzd Jan 15 '11 at 15:26