3

The write procedure to my file was as follows (in the mode which I call non-clustered)

  1. Write an object to the current position of the file. Note the position of write in another file (called the index file) so I know where have I placed the objects.
  2. Leave some space (Randomly 1/2/3/4 KB of space) by writing zero bytes
  3. Repeat steps 1 and 2

Now I decided to read the objects back from the file. But I wanted to use BufferedInputStream. However when I encapsulate a BufferedInputStream inside an ObjectInputStream I get errors after reading some of the objects. I am guessing this happens after One buffered Read (i.e. as many objects as can fit in the buffer are read once, the next time I get an error).

On the Other hand encapsulating a FileInputStream directly inside a ObjectInputStream works without any problem.

If needed, I will provide the file writing code too. Feel free to ask anything about the code below.

public class RecordsFileReader {
    RecordsFile rFile;
    Iterator itr;
    FileInputStream fis;
    ObjectInputStream ois;

// The constructor
public RecordsFileReader(RecordsFile rFile) throws IOException, ClassNotFoundException {
    this.rFile = rFile;
    fis = new FileInputStream(rFile.getFileName());


    ObjectInputStream ois2 = new ObjectInputStream(new FileInputStream(rFile.getFileName() + ".index"));



    rFile.recordsLocationList =  (ArrayList <Long>) ois2.readObject();
    itr = rFile.recordsLocationList.iterator();
   /**********************************************************/
   /*          HERE IS THE PROBLEM.                          */
   /* Doesnt work when I additionally use BufferedInputStream*/
   /**********************************************************/

    ois = new ObjectInputStream(fis);

   /**********************************************************/     
}

public Tuple readNext() throws IOException, ClassNotFoundException {
    if(!itr.hasNext())
        return null;
    Long nextRecordPosition = itr.next();
    fis.getChannel().position(nextRecordPosition);
    //System.out.println((Tuple) ois.readObject());
    return ((Tuple) ois.readObject());
}

public void close() throws IOException {
    ois.close();
    fis.close();



}

public boolean hasNext() {
    return itr.hasNext();

}

}

public class RecordsFile {

boolean clustered;
private String fileName;

public RecordsFile(String fileName, boolean clustered) throws IOException {
    this.fileName = fileName;
    this.clustered = clustered;
}

/*
The byte positions at which the records are located in the file.
*/
ArrayList<Long> recordsLocationList= new ArrayList<Long>();

public String getFileName() {
    return fileName;
}

}

This is the change that is causing the error : ois = new ObjectInputStream(new BufferedInputStream(fis, 4096)); instead of ois = new ObjectInputStream(fis);

The error is java.io.StreamCorruptionException: invalid type code : 00

EDIT :

I have now figured out the problem. While my fis was being positioned to a new position, my bis was not being skipped to that new position. Instead bis was trying to read from the old position only and hence the exception

AnkurVj
  • 7,958
  • 10
  • 43
  • 55
  • what is the error you get with BufferedInputStream ? Technically , adding a BIS should never cause a problem( on account of its buffered style of reading because thats an implementation detail ).Also can you show how you wrap the OIS into a BIS which causes the error ? – Bhaskar Sep 14 '11 at 21:08
  • I would have investigated what exactly was causing the error , but you may close the question if you feel right. – Bhaskar Sep 14 '11 at 21:12
  • @Bha `ois = new ObjectInputStream(new BufferedInputStream(fis, 4096));` instead of `ois = new ObjectInputStream(fis);` – AnkurVj Sep 14 '11 at 21:13
  • @Bha I have also added the error I am getting in the question. (I was mistakenly adding BIS to the wrong file and hence was getting it to run without error. However, the error is still there) – AnkurVj Sep 14 '11 at 21:16

1 Answers1

2

This is indicative of a case where the bytes being read back from the stream ( and from the file ) are being interpreted as an object ( by the OIS ) but actually these bytes are something else ( not a byte representation of an actual object ). This may be because of the buffer size being specified explicitly ( combined with the fact that you are setting the position manually ).

I would suggest to try without specifying the buffer size explicitly.

ois = new ObjectInputStream(new BufferedInputStream(fis))

Bhaskar
  • 7,443
  • 5
  • 39
  • 51
  • even without setting buffer size explicitly I get the same error. I understand it is being caused because I am setting position manually while bis is unaware that the underlying fc has been repositioned. – AnkurVj Sep 14 '11 at 21:41
  • 1
    Now I am beginning to think of it , BIS does not buffer based on custom logic ( per object ) , it can only buffer based on raw bytes , while this use case requires it to buffer one or more ( but not a fraction there of ) object bytes. I am getting inclined to say that you would need to write a custom BIS for that purpose. – Bhaskar Sep 14 '11 at 21:49
  • Well Java is pretty poor then. All I wanted to do was to be able to write objects in a file at various locations and being able to read, not one at a time, but by big blocks at a time which may contain one or more objects. I could have done this in c++ using simple read((sizeof)object * 20) and using my index to parse through the read bytes. In java I have wasted 3 days trying to figure this out and I am still nowhere. So much for the ease of use! Thankyou very much for y our effort – AnkurVj Sep 14 '11 at 21:55
  • 1
    @AnkurVj , I would not agree with your view on Java being poor. If you notice , in your C++ code , you are writing code to tell it *how* you want it to buffer bytes ( by specifying sizeof and *20); Its the same in Java too - you would have to specify in code how the BIS should buffer - per object ( you would need to extend a class and override some methods to do that - but thats a different point ) On the converse , Java facilitates so much functionality by IO libraries - you would have a much steeper curve coding similar things in C++. – Bhaskar Sep 14 '11 at 22:12
  • When i do a read or write using file input stream of a specified number of bytes, is each byte written using a separate system call or all bytes written using a single system call ? – AnkurVj Sep 14 '11 at 22:29