0

Here's my code:

 try {

                Uri uri = Uri.parse("file:///storage/emulated/0/Download/information.csv");
                File file = new File(uri.getPath());
                //Read the file
                BufferedReader br = new BufferedReader(new FileReader(file));
                String line;
                boolean firstLine = true;

                while ((line = br.readLine()) != null) {
                    System.out.println("Print the contents from the file :" + line);
                    if (firstLine) {
                        firstLine = false;
                        continue;
                    } else {

                            //deserialize the string to Object
                            td = TransferData.fromString(line); //Where td is an object 

                            //deserialize the string to Object
                            System.out.println("deserialized: " + td);



               }

However, I get an exception on this line:

td = TransferData.fromString(line);

and from my fromString function:

/** Read the object from Base64 string. */
    public static TransferData fromString( String s ) throws IOException, ClassNotFoundException     {
        byte [] data = Base64.decode(s, Base64.DEFAULT);
        ObjectInputStream ois = new ObjectInputStream(
                new ByteArrayInputStream(  data ) );
        Object o  = ois.readObject();
        ois.close();
        return (TransferData)o;
    }

The exception is StreamCorruptedException but I'm not sure why that is. I want to be able to read in a string and deserialize the string.

EDIT:

  /** Write the object to a Base64 string. */
    public static String toString(Serializable o) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(output);
        oos.writeObject(o);
        oos.close();
        return new String(Base64.encode(output.toByteArray(), Base64.DEFAULT));
    }



//SerialVersionID
  private static final int serialVersionUID = 10032014;
5
  • Where is your ObjectOutputStream? Which object are you trying to deserialize? Are you sure that the serialVersionUID is correctly configured? Commented Oct 20, 2014 at 13:08
  • Remeber that, as per the Javadoc, An ObjectInputStream deserializes primitive data and objects previously written using an ObjectOutputStream. If your goal is to read a string from a file ObjectInputStream is not what you need. Commented Oct 20, 2014 at 13:12
  • Well here is the thing. I have two devices, one device takes an object and converts it to a string. Then saves the string to a file. The other devices reads the string in that file and deserializes it. Commented Oct 20, 2014 at 13:37
  • My objectOutputStream is in my toString method. Where would I need an output stream here? Commented Oct 20, 2014 at 13:39
  • The StreamCorruptedException is "Thrown when control information that was read from an object stream violates internal consistency checks." That means your code that serializes the object to the file is not correct. Commented Oct 20, 2014 at 14:09

1 Answer 1

4

I can see some flaws in your code:

  1. You are creating a new ObjectInputStream each time you read a new line (which is probably causing the StreamCorruptedException)
  2. If you are reading the file via BufferedReader you don't need an ObjectInputStream and viceversa.
  3. I can't understand, why you are doing a Base64.decode of the string?
  4. You must assure that the serialVersionUID is coherent.

If I understood well you want to serialize an object to a file and then deserialize it. First of all you should have an entity (your object) which implements the Serializable interface:

public class Foo implements Serializable{
    static final long serialVersionUID = 42L;
    //class code...
}

Now you can safely save your object (or a list of it) to a file:

FileOutputStream fos = new FileOutputStream("myFoo.tmp");
ObjectOutputStream oos = new ObjectOutputStream(fos);

Foo foo = new Foo();
//Fill the object.

oos.writeObject(foo);

If you need to read that file you can now do:

FileInputStream fis = new FileInputStream("myFoo.tmp");
ObjectInputStream ois = new ObjectInputStream(fis);

Foo mySavedFoo = (Foo) ois.readObject();

If you need to save a list of objects you can use the ArrayList implementation of List which implements Serializable:

FileOutputStream fos = new FileOutputStream("myFoos.tmp");
ObjectOutputStream oos = new ObjectOutputStream(fos);

List<Foo> foos = new ArrayList<Foo>();
//Fill the list.

oos.writeObject(foos);

//...

FileInputStream fis = new FileInputStream("myFoos.tmp");
ObjectInputStream ois = new ObjectInputStream(fis);

ArrayList<Foo> mySavedFoo = (ArrayList<Foo>) ois.readObject();

ADDENDUM

A StreamCorruptedException is Thrown when control information that was read from an object stream violates internal consistency checks.

When an object is written on a file using a ObjectOutputStream, it's added of a properly formatted header used when the object is deserialized. If such header isn't consistent you have a violation of internal consistency checks.

When you are reading, line by line (line = br.readLine()), your file, you are removing such header and thus your ObjectInputStream can't properly read the object you saved. Furthermore you are decoding a Base64, scrambling even more the data read. Add that for every line you create a new ObjectInputStream and StreamCorruptedException appears.


EDIT

From your edit I can understand better what is your problem.

public static String toString(Serializable o) throws IOException {
    //                   what is this? ^
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(output);
    oos.writeObject(o); //Here you are saving a Serializable object to... what? Which file?
    oos.close();
    return new String(Base64.encode(output.toByteArray(), Base64.DEFAULT));
}

Just like my example before, you are storing a Serializable object via ObjectOutputStream (where BTW?), but Serializable is only an interface. It would be better if you used the class implementing it. Following my example it would become:

public static String toString(Foo o) throws IOException { //...

The Base64.encode is done AFTER the object is saved to the file!! There is no "encryption"! Also the encoding is done to the output object which is ByteArrayOutputStream and nothing has to do with the real data stored in o.

Sign up to request clarification or add additional context in comments.

12 Comments

Nice answer, Narmer. +1
Side thought, would it change anything if I am encrypting (on device 1) and decrypting (on devic 2) the string inside the file? Also when you say file header.. do you mean that the file header data has to be the same? edit: I edited my post to show my toString method.
The encryption of data should be done before the data is stored and the decryption after it is retrieved. But I can't quite understand what you wwant to do... The header is internal, you should not modify nor create it.
the file header would be the same but I would not want to turn it into an object. Btw, I updated my post to reveal my serialversionUID. Does it have to be long?
Mmmh... You are mixing things. Forget for a second of the header, it complicates things and it's not important now. You have to understand what comes first: serialization. What are you passing in oos.writeObject(o);? What's o (instance)?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.