3

I have a method that writes data from a list to a file, a method that reads data from a file into a list and a method that writes data from a list in a file to the specified number of times. I'm trying to extract data from a file after I use the first method writeFile () everything works fine. I read the data from the file into the list by readFile () method. After that I use my method which writes to the file the number of times I need, everything is fine, it writes multyWrite (). But after that I can not read the data from the file in the readFile () method since I get `

Exception stack trace:

 Exception in thread "main" java.io.StreamCorruptedException: invalid type code: AC     
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1599)   
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)      
at ProductService.readFile(ProductService.java:47)  
at Main.main(Main.java:21)

I know that I should use objectOutputStream.reset (), but where would it be better to use it?

private String fileName;
    private ProductInterface<FlyingMachine> productService = new ProductInterfaceImpl();
    private ObjectOutputStream objectOutputStream;
    private FileOutputStream fileOutputStream;


    public ProductService(String fileName) throws IOException {
        this.fileName = fileName;
        fileOutputStream = new FileOutputStream(fileName);
        this.objectOutputStream = new ObjectOutputStream(fileOutputStream);
    }

public void writeFile() throws IOException {
        try {
            for (FlyingMachine f : productService.getProductContainer()) {
                objectOutputStream.writeObject(f);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (objectOutputStream != null) {
                objectOutputStream.flush();
                objectOutputStream.close();
                fileOutputStream.close();
            }
        }
    }`

public void readFile() throws IOException {
        ObjectInputStream objectInputStream = null;
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(fileName);
            objectInputStream = new ObjectInputStream(fileInputStream);
            while (fileInputStream.available() > 0) {
                FlyingMachine flyingMachine = (FlyingMachine) objectInputStream.readObject();
                productService.getProductContainer().add(flyingMachine);
            }
        } catch (ClassNotFoundException | EOFException e) {
            e.printStackTrace();
        } finally {
            if (objectInputStream != null) {
                objectInputStream.close();
                fileInputStream.close();
            }
        }
    }

public void multyWrite(int number) throws IOException {
        for (int i = 0; i < number; i++) {
            try {
                fileOutputStream = new FileOutputStream(fileName, true);
                objectOutputStream = new ObjectOutputStream(fileOutputStream);
                for (FlyingMachine f : productService.getProductContainer()) {
                    objectOutputStream.writeObject(f);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (objectOutputStream != null) {
                    objectOutputStream.flush();
                    objectOutputStream.close();
                }
            }
        }
    }
Mefisto_Fell
  • 876
  • 1
  • 10
  • 30

1 Answers1

1

You create a new ObjectOutputStream in the constructor. In writeFile you use that OOS instance and close it. But in multyWrite you don't use it and instead create new instances.

Now when you call multyWrite without having called writeFile first, that first OOS will still be open, but the OOS you create in multyWrite doesn't know that - thus causing your file to have two OOS headers after another.

And then when you try to read such a file, the ObjectInputStream will find the first header (all is fine) and then unexpectedly find the second header, while it expected a type code. That header starts with 0xAC, hence throwing the exception message "invalid type code: AC".

To fix this, either have multyWrite use the OOS constructed in your constructor, the same way writeFile does, or make sure that that OOS is closed before you create a new one.

It's generally not a good idea to open a stream (of any kind) in a constructor and then rely on external code calling a specific method to close it. Better create streams when you need them and close them directly.

Max Vollmer
  • 8,412
  • 9
  • 28
  • 43