0

I have a trouble with reading multiple objects from InputStream(i.e. from file). I receive the exception:

java.io.StreamCorruptedException: invalid type code: AC
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1379)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
    at com.socket.Client.readFromFile(Client.java:63)
    at com.socket.Client.main(Client.java:44)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

I have managed to read/write only one object, it's OK. I can write many objects, it's OK too. But I cannot read more than one object from file. Why does it happen so?

EDIT:

NB! It seems I have faced with the problem of implementing of List in Externalazible class. How to implement it correcly?

My 'Main' code:

public class Client {


public static void main(String[] args) {

    if (args[0] == null || args[1] == null) {
        System.out.println("No arguments entered!");
        System.exit(0);
    }

    try (Socket clientSocket = new Socket("localhost", 3000);
         OutputStream outbound = clientSocket.getOutputStream();
         BufferedReader inbound = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));) {

        outbound.write((args[0] + "\n").getBytes());
        outbound.write("End\n".getBytes());

        List<StockQuote> stockQuotes = new ArrayList<>();
        String quote;
        while (true) {
            quote = inbound.readLine();

            if (quote != null && quote.equals("End"))
                break;

            stockQuotes.add(new StockQuote(args[0], new Double(quote)));
        }

        writeInFile(args[1], stockQuotes);
        stockQuotes.clear();

        stockQuotes = readFromFile(args[1]);
        if (stockQuotes != null)
            for (StockQuote stockQuote : stockQuotes)
                System.out.println("The " + stockQuote.getSymbol() + " price is " + stockQuote.getPrice());

    } catch (UnknownHostException e) {
        System.out.println("No such host available!");
    } catch (IOException e) {
        System.out.println("Server not reachable or down!!");
    }
}

private static List<StockQuote> readFromFile(String filename) {

    File file = new File(filename);

    try (ObjectInputStream readFromFile = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)));) {
        return (List<StockQuote>) readFromFile.readObject();
    } catch (FileNotFoundException e) {
        System.out.println("'" + filename + "' is not found in " + file.getPath());
    } catch (IOException e) {
        e.printStackTrace();
        System.out.println("Something gone wrong in the process of reading from '" + file + "'");
    } catch (ClassNotFoundException e) {
        System.out.println("Cast to class is wrong!");
    }

    return null;
}

private static void writeInFile(String filename, List<StockQuote> stockQuotes) {

    File file = new File(filename);

    try (ObjectOutputStream writeInFile = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file, true)));) {
            writeInFile.writeObject(stockQuotes);
    } catch (FileNotFoundException e) {
        System.out.println("'" + filename + "' is not found in " + file.getPath());
    } catch (IOException e) {
        System.out.println("Something gone wrong in the process of writing to '" + file + "'");
    }
}

}

Externalizable 'StockQuote' class:

public class StockQuote implements Externalizable {

private String symbol;
private double price;
private List<StockQuote> stockQuoteList;

public StockQuote() {
}

public StockQuote(String symbol, double price) {
    this.symbol = symbol;
    this.price = price;
}

public String getSymbol() {
    return symbol;
}

public void setSymbol(String symbol) {
    this.symbol = symbol;
}

public double getPrice() {
    return price;
}

public void setPrice(double price) {
    this.price = price;
}

@Override
public void writeExternal(ObjectOutput out) throws IOException {
    out.writeObject(stockQuoteList);
}

@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
    stockQuoteList = (List<StockQuote>) in.readObject();
}

}

Result:

As the result, I receive something like "The null price is 0.0". It says that I serialize my List but my Objects inside it are not serialized, why?

NB!

And could you take me one more tip, how is better to write strings, list and so on in Externalizable classes as out.writeObject or there is beter way to do it?

Viktor M.
  • 4,393
  • 9
  • 40
  • 71
  • You can't append to files written by ObjectOutputStream and read them with a single ObjectInputStream, unless you take special measures. – user207421 May 08 '14 at 21:53

1 Answers1

2

Your reads and writes are not symmetric.

To write two stock quotes, you

  • open a new ObjectOutputStream
  • write a StockQuote
  • close the ObjectOutputStream
  • open a new ObjectOutputStream
  • write a StockQuote
  • close the ObjectOutputStream

To read these two StockQuotes, you

  • open an ObjectInputStream
  • read a StockQuote
  • read a StockQuote
  • close the ObjectInputStream

Each time you open a new ObjectOutputStream, a serialization header is written to the underlying stream.

My advice: store all the StockQuotes to a list, and write this list to the ObjectOutputStream when you're done. On the receiver end, read the list.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • I have edit my source code but I have faced with a problem of list serializable. I tried to find any examples how to implement list serializing but no one normal example about it. Could you show me a small example how to write and read List? – Viktor M. May 09 '14 at 11:20
  • oos.writeObject(list) to crite, and oos.readObject(list) to read. Your readExternal() and writeExternal() methods in StockQuote were fine. The only thing you should have changed in your original program is that instead of writing 2 stock quotes, you should store them in a list, and when you're done, write this list. – JB Nizet May 09 '14 at 14:13