-1

A brief description of a program I am building. The program has 3 classes, a user class, a port class, and a vehicle class.

The port class contains an Id property of String type and Arraylist property that contains all onsite vehicles. The Vehicle class contains an Id property and another property of Port class called current_port. The Vehicle class is a superclass to the ship class and the truck class, which in turns is a superclass for the basic truck class and the tanker class. Using ObjectInputStream and ObjectOutputStream, both classes have method that allows for the entry of their objects into their respective files.

For the Port class, I have no issue with writing, appending, reading, and updating its object in its file. However, the problem surfaces when I try to create an object of basic truck and tanker type. Specifically, when a new vehicle is created, the file of the port class is updated to reflect the inclusion of another vehicle.The problem surfaces when I create an object of basic truck class and tanker class. While I am able to write them into the vehicle file and update the port file, when I try to read all retrieve all vehicles from the vehicle file, I got the following exception. This exception only appears when I create vehicles of basic truck and tanker type:

Exception in thread "main" java.lang.ClassCastException: class java.lang.String cannot be cast to class java.io.ObjectStreamClass (java.lang.String and java.io.ObjectStreamClass are in module java.base of loader 'bootstrap')
at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1924)
at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2075)
at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1922)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2248)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1757)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:538)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:496)
at java.base/java.util.ArrayList.readObject(ArrayList.java:899)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:577)
at java.base/java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1100)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2447)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2281)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1757)
at java.base/java.io.ObjectInputStream$FieldValues.<init>(ObjectInputStream.java:2630)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2481)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2281)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1757)
at java.base/java.io.ObjectInputStream$FieldValues.<init>(ObjectInputStream.java:2630)
at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2481)
at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2281)
at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1757)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:538)
at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:496)
at Vehicle.getVehicles(Vehicle.java:20)
at Main.main(Main.java:8)

The following is my code:

AppendObjectOutputStream

public class AppendObjectOutputStream extends ObjectOutputStream {
    AppendObjectOutputStream() throws IOException
    {

        // Super keyword refers to parent class instance
        super();
    }

    // Constructor of this class
    // 1. Parameterized constructor
    AppendObjectOutputStream(OutputStream o) throws IOException
    {
        super(o);
    }

    // Method of this class
    public void writeStreamHeader() throws IOException
    {
        return;
    }
}

Port Class:

import java.io.*;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

public class Port implements Serializable {
    public String Pid;
    public ArrayList<Vehicle>vehicles = new ArrayList<Vehicle>();

    public Port(String Pid){
       this.Pid = Pid;}

    public boolean equals(Port port) {
        if (port == this) {
            System.out.println("true");
            return true;
        }

        return this.Pid.equals(port.Pid);


    }
    public static ArrayList<Port> getPorts(){
        ArrayList<Port> port_list = new ArrayList<Port>();
        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("port.txt"));
            while (true){
                try{
                    Port port = (Port) ois.readObject();
                    port_list.add(port);
                } catch (EOFException e){
                    break;
                }
                catch (ClassNotFoundException e){
                    e.printStackTrace();
                }

            }
        } catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e){
            e.printStackTrace();
        }
        return port_list;
    }
    public static void inputPortIntoFile(File file, Port port){
        if (file.length() == 0){
            try{
                ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("port.txt"));
                oos.writeObject(port);
                oos.close();
            } catch (FileNotFoundException e){
                e.printStackTrace();
            } catch (IOException e){
                e.printStackTrace();
            }
        }
        else {
            try{
                AppendObjectOutputStream oos = new AppendObjectOutputStream(new FileOutputStream("port.txt", true));
                oos.writeObject(port);
                oos.close();
            } catch (FileNotFoundException e){
                e.printStackTrace();
            } catch (IOException e){
                e.printStackTrace();
            }
        }
    }
    public static void updatePort(Port port){
        System.out.println(port.vehicles);
        ArrayList<Port> port_list = Port.getPorts();
        File file = new File("port.txt");
        for (int i =0; i<port_list.size(); i++){
            if (port_list.get(i).equals(port)){
                port_list.set(i, port);
            }
        }
        file.delete();
        try{
            file.createNewFile();
            for (Port p: port_list){
                Port.inputPortIntoFile(file, p);
            }
        } catch (IOException e){
            e.printStackTrace();
        }
    }

    public static Port queryPortbyID(String Pid){
        for (Port port: getPorts()){
            if (port.Pid.equals(Pid)){
                return port;
            }
        }
        System.out.println("This port does not exist");
        return null;
    }
    public static void createNewPort(){
        String Pid = "";
        Random random = new Random();
        for (int i = 1; i<=10; i++){
            Pid = Pid + random.nextInt(10);
        }
        File file = new File("port.txt");
        Port new_port = new Port(Pid);
        inputPortIntoFile(file, new_port);
    }
    public void accept_vehicles(Vehicle vehicle){
        this.vehicles.add(vehicle);
        Port.updatePort(this);

    } 
}

Vehicle Class:

import java.io.*;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
public class Vehicle implements Serializable {
    public String Vid;
    public Port current_port;

    public Vehicle(String Vid, Port port){
        this.Vid = Vid;
        this.current_port = port;
    }
    public static ArrayList<Vehicle> getVehicles(){
        ArrayList<Vehicle> vehicle_list = new ArrayList<Vehicle>();
        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("vehicle.txt"));
            while (true){
                try {
                    Vehicle vehicle = (Vehicle) ois.readObject();
                    System.out.println(vehicle);
                    vehicle_list.add(vehicle);
                } catch (EOFException e){
                    break;
                } catch (ClassNotFoundException e){
                    e.printStackTrace();
                }
            }
        } catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e){
            e.printStackTrace();
        }
        return vehicle_list;
    }
    public static void inputVehicleIntoFile(File file, Vehicle vehicle){
        if (file.length() == 0 ){
            try{
                ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("vehicle.txt"));
                oos.writeObject(vehicle);
                oos.close();
            } catch (FileNotFoundException e){
                e.printStackTrace();
            } catch (IOException e){
                e.printStackTrace();
            }
        }
        else {
            try{
                AppendObjectOutputStream oos = new AppendObjectOutputStream(new FileOutputStream("vehicle.txt", true));
                oos.writeObject(vehicle);
                oos.close();
            } catch (FileNotFoundException e){
                e.printStackTrace();
            } catch (IOException e){
                e.printStackTrace();
            }
        }
    }
    public static Vehicle queryVehiclebyID(String Vid){
        for (Vehicle vehicle: Vehicle.getVehicles()){
            if (vehicle.Vid.equals(Vid)){
                return vehicle;
            }
        }
        System.out.println("Vehicle not found");
        return null;
    }
    public static Vehicle createNewVehicle(){
        Scanner scanner = new Scanner(System.in);
        String Vid = "";
        Random random = new Random();
        File file = new File("vehicle.txt");
        for (int i = 1; i<=10; i++){
            Vid = Vid + random.nextInt(10);
        }
        System.out.println("Please ionput the id of the port you would like to assign this vehicle to");
        String Pid = scanner.nextLine();
        Port port = Port.queryPortbyID(Pid);
        System.out.println("Please input the type of vehicle (ship/basic/tanker)");
        String type = scanner.nextLine();
        if (type.equals("ship")){
            Vehicle vehicle = new ship("SH"+Vid, port);
            inputVehicleIntoFile(file, vehicle);
            return vehicle;
        }
        else if (type.equals("basic")){
            Vehicle vehicle = new basic("BT"+Vid, port);
            inputVehicleIntoFile(file, vehicle);
            return vehicle;
        }
        else {
            Vehicle vehicle = new tanker("TT"+Vid, port);
            inputVehicleIntoFile(file, vehicle);
            return vehicle;
        }
    }
}

class ship extends Vehicle{
    public ship(String Vid, Port port){
        super(Vid, port);
    }
}

class truck extends Vehicle{
    public truck(String Vid, Port port){
        super(Vid, port);
    }
}

class tanker extends truck{
    public tanker(String Vid, Port port){
        super(Vid, port);
    }
}

class basic extends truck{
    public basic(String Vid, Port port){
        super(Vid, port);
    }
}

User Class

public class User {
public static void addPort(){
    Port.createNewPort();
}
public static void addVehicle(){
        Vehicle new_vehicle = Vehicle.createNewVehicle();
        new_vehicle.current_port.accept_vehicles(new_vehicle);

    }
}

Main Class

public class Main {
    public static void main(String[] args) {
        User.addPort();
        User.addVehicle();
        User.addVehicle();
        User.addVehicle();
        Vehicle.getVehicles();
    }
}

Do you know what could have caused this issue and how can I fix it? Thank you very much

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Please edit your question and add your `main` method. – tgdavies Sep 01 '23 at 02:43
  • @tgdavies Hi just edited it – Trung Lương Sep 01 '23 at 02:56
  • 1
    That code doesn't match the stack trace, which says that `getVehicles` is being called at `Main.java:3`, where your code calls it at line 7. – tgdavies Sep 01 '23 at 03:03
  • @tgdavies Hi, I am sorry I forgot that I already changed the codes in the main method. I am going to update the stack trace now – Trung Lương Sep 01 '23 at 03:08
  • @tgdavies Hi I just updated the stack trace. Sorry for the trouble – Trung Lương Sep 01 '23 at 03:10
  • 1
    It looks as though you're using the answer from https://stackoverflow.com/questions/1194656/appending-to-an-objectoutputstream ? You need to also show the code for your `AppendObjectOutputStream`. – tgdavies Sep 01 '23 at 03:16
  • @tgdavies Hi, I ve already put it on top of the Port class – Trung Lương Sep 01 '23 at 03:22
  • 1
    You're trying to use `ObjectOutputStream` in a way it wasn't designed for. Use a DB, or write everything at once. – tgdavies Sep 01 '23 at 03:29
  • @tgdavies Hi, I am able to append new objects to the files just fine. My primary problem is when I create, say, a tanker truck (tanker class), the port file will successfully be updated, and the new object is successfully written into the vehicle file. However, calling the getVehicles will trigger the above Exception – Trung Lương Sep 01 '23 at 03:32
  • @tgdavies So now every time the user create a new port or vehicle, I will have to extract all of the existing vehicles into an arraylist, add the new vehicle into it, delete the existing file, create a new file, and then write the whole arraylist into the file? – Trung Lương Sep 01 '23 at 03:34
  • 1
    An object is only appended "just fine" if you can then read it successfully. – tgdavies Sep 01 '23 at 03:37
  • Use a DB, like https://www.h2database.com/html/main.html -- it's pure Java, no installation required. – tgdavies Sep 01 '23 at 03:38
  • @tgdavies I'll consider it. Thank you for your help – Trung Lương Sep 01 '23 at 03:58
  • @tgdavies I just made some minor adjustments to the classes. Surprisingly, everything is fine when I remove the basic and tanker subclasses. Objects of these 2 classes are now direct objects of the truck class, which is a subclass of Vehicle class. I wonder what is the reason for this – Trung Lương Sep 01 '23 at 04:31
  • Hard to say without more information, such as how you run this code, but I guessed and I cannot reproduce your problem. Evidently this is not the real code. NB (1) Serialized data is not text and should not be written to a file named `.txt`. (2) Putting things into a file is output, not input. – user207421 Sep 01 '23 at 04:49
  • @user207421 That solved everything. Thank you very much. I have been blindly following online tutorials and many of them use txt. – Trung Lương Sep 01 '23 at 05:01
  • The suffix should make no difference. – tgdavies Sep 01 '23 at 05:42

0 Answers0