Reading objects from a random access file

I wrote a file using the Java FileChannel class, which uses RandomAccessFiles. I wrote objects in different places of the file. The objects were variable in size, but they were all the same. I wrote objects using the following idea:

  ByteArrayOutputStream bos = new ByteArrayOutputStream();       ObjectOutput out =  ObjectOutputStream (bos);       out.writeObject();       byte [] recordBytes = bos.toByteArray(); 
  ByteBuffer rbb = ByteBuffer.wrap(recordBytes);  while (rbb.hasRemaining()) {       fileChannel.write();   } > 

Code>

Now I want to read from such a file. I do not want to indicate the number of bytes read. I want to be able to read an object directly using Object Input Stream. How to achieve this?

I need to use random access files because I need to write in different positions in the file. I also record in a separate data structure, in the places where the objects were recorded.

+4
source share
4 answers

I need to use random access files because I need to write for different positions in the file.

No no. You can move FileOutputStream or FileInputStream through your channel.

This will greatly simplify your recording code: you will not need to use a buffer or channel, and depending on your needs, you can also omit ByteArrayOutputStream . However, as you noted in the comment, you wonโ€™t know the size of the object in advance, and ByteArrayOutputStream is a useful way to verify that you are not overflowing the allocated space.

 Object obj = // something FileOutputStream fos = // an initialized stream ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(obj); oos.flush(); if (bos.size() > MAX_ALLOWED_SIZE) throw // or log, or whatever you want to do else { fos.getChannel().position(writeLocation); bos.writeTo(fos); } 

To read objects, do the following:

 FileInputStream fis = // an initialized stream fis.getChannel().position(offsetOfSerializedObject); ObjectInputStream iis = new ObjectInputStream(new BufferedInputStream(fis)); Object obj = iis.readObject(); 

One comment here: I wrapped FileInputStream in a BufferedInputStream . In this particular case, when the file stream is moved before each use, this can provide a performance advantage. Keep in mind, however, that a buffered stream can read more bytes than necessary, and there are situations where object streams that are needed as objects are used where it would be a very bad idea.

+3
source

Why does seek not work for you? I believe that you need seek() correct the locations, and then just read the objects using the stream of objects. Also, if you store the correct locations of serialized objects, why don't you keep their sizes? In this case, you can apply an ObjectInputStream to the bytes that you are reading from the file.

+2
source

The simplest solution that comes to mind is to write the length of the array before writing the array itself:

 while(rbb.hasRemaining()) { fileChannel.writeLong(recordBytes.length); fileChannel.write(rbb); } 

When reading an object, you read the length first. This will tell you how many more bytes to read to get your object. Similar to what you are already doing on the write side, you can read the data in byte[] and then use ByteArrayInputputStream and ObjectInputStream .

+1
source

You can use a FileInputStream built on a RandomAccesFile FileDescriptor object, for example:

 FileDescriptor f = raf.getFD(); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f)); 

Assuming RandomAccessFile is called raf.

+1
source

All Articles