views:

190

answers:

2

I'm writing an Android application. One problem is your app cannot contain a file whose uncompressed size is bigger than about 1Mb. I have a serialized object that I want to load that totals about 2Mb. My plan was to split this file into two smaller files, then load the object by combining both files at runtime.

However, I cannot work out how to use e.g. InputStream and ObjectInputStream to specify that I want to read the data from two input streams. How can I do this?

For example, say my object was split between file O1 and O2. How can I say "Load the object by reading the data from O1 then from O2"?

+1  A: 

ObjectInputStream just takes the InputStream in its constructor, so clearly the task is implementing an InputStream concrete subclass that reads two files in sequence (rather than just one as FileInputStream does). Basically your concrete subclass must implement read(byte[]) by delegating to the first, then (when that's exhausted) the second one of two FileInputStreams it holds as attributes (pass them into your concrete subclass's constructor).

Alex Martelli
I've considered doing it this way, but I would have thought this functionality would be hidden somewhere. I'd rather not write a new class if I can help it.
DrDefrost
If you have `SequenceInputStream` in your Android SDK (sorry, don't have one to check), that's the predefined implementation that you're looking for, as Tom's comment and William's answer also indicate.
Alex Martelli
+3  A: 

As Tom Hawtin pointed out in the comments, you should be able to use Java's built-in SequenceInputStream class to deserialize an object that is split across multiple files. This approach also allows you to deserialize an object split across any number of files, because SequenceInputStream's constructor accepts two InputStream objects, one of which could be another SequenceInputStream.

I created a small example that should work on Android, although I have only tested it on a desktop Java installation. The example works on the assumption that you have serialized an object of type Foo and split the serialized version between two files names myobj.part1 and myobj.part2.

The example is pretty self explanatory, but if you have any questions, please let me know.

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.SequenceInputStream;

...

ObjectInputStream in = null;

try {
    in = new ObjectInputStream(
        new SequenceInputStream(
                new FileInputStream("myobj.part1"),
                new FileInputStream("myobj.part2")));

    Foo foo = (Foo) in.readObject();

    // Do something with the deserialized object...
    foo.doSomething();
} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (in != null) {
        try { 
            in.close();
        } catch (IOException e) { }
    }
}
William Brendel