Search code examples
javajava.util.scannersubclass

How to read values and assign them to fields when using a scanner to scan a text file?


I'm new to java and I've been working on a project with three classes that use scanner objects to read data from a text file and assign them to the fields of two of the classes. My problem is that the values are being assigned to the fields of one class, but not the other.

These are the three classes: The Vehicle class, which has a readDetails method that reads its own data from the text file.

import java.util.NoSuchElementException;
import java.util.Scanner;

public class Vehicle {
    // Vehicle Name
    private String vehicleModel;
    // Code of the vehicle
    String vehicleCode;
    // Number of times the vehicle was rented
    private int timesRented;
    // To show if the vehicle is on loan or not
    private boolean onRent;
    // The cost of a vehicle to rent
    private int price;
    // Vehicle plate number
    private int vehiclePlateNum;
    // Whether the car is convertible or not.
    private boolean isConvertible;
    // the number of doors on the car.
    private int numOfDoors;

    /**
     * Constructor for objects of class Vehicle
     */
    public Vehicle() {
    }

    /**
     * Print the details of the vehicle
     */
    public void printDetails() {
        System.out.println("Vehicle model: " + vehicleModel + "; code: " + vehicleCode
                + "; timesRented: " + timesRented + "; onRent: " + onRent + "; price: " + price
                + "; vehiclePlateNum: " + vehiclePlateNum);
    }

    /**
     * Read the data for a vehicle.
     * 
     * @param scanner The scanner to use to read the data.
     */
    public void readDetails(Scanner scanner) {
        try {
            while (scanner.hasNextLine()) {
                String lineOfText = scanner.nextLine().trim();

                Scanner scanner2 = new Scanner(lineOfText);
                scanner2.useDelimiter(",");
                vehicleModel = scanner2.next().trim();
                vehicleCode = scanner2.next().trim();
                timesRented = Integer.parseInt(scanner2.next().trim());
                onRent = Boolean.parseBoolean(scanner2.next().trim());
                price = Integer.parseInt(scanner2.next().trim());
                vehiclePlateNum = Integer.parseInt(scanner2.next().trim());
                scanner2.close();
                printDetails(); // call printDetails() to print the vehicle details
            }
        }
        catch (NoSuchElementException e) {
            System.out.println("Error reading data: " + e.getMessage());
        }
    }
}

The Car class, which is a subclass of Vehicle. It also has a readDetails method that reads its own data from the text file.

import java.util.NoSuchElementException;
import java.util.Scanner;

public class Car extends Vehicle {
    // Whether the car is convertible or not.
    private boolean isConvertible;
    // the number of doors on the car.
    private int numOfDoors;

    public Car() {
        super();
        isConvertible = this.isConvertible;
        numOfDoors = this.numOfDoors;
    }

    @Override
    public void printDetails() {
        System.out.println("Vehicle model: " + ShowVehicleModel() + "; code: " + ShowVehicleCode()
                + "; timesRented: " + ShowTimesRented() + "; onRent: " + ShowOnRent() + "; price: "
                + ShowPrice() + "; vehiclePlateNum: " + ShowVehiclePlateNum() + "; isConvertible: "
                + isConvertible + "; numOfDoors: " + numOfDoors);
    }

    /**
     * Read the data.
     */
    @Override
    public void readDetails(Scanner scanner) {
        try {
            while (scanner.hasNextLine()) {
                String lineOfText = scanner.nextLine().trim();

                Scanner scanner2 = new Scanner(lineOfText);
                scanner2.useDelimiter(",");
                super.readDetails(scanner2);
                this.isConvertible = Boolean.parseBoolean(scanner2.next().trim());
                this.numOfDoors = Integer.parseInt(scanner2.next().trim());
                scanner2.close();
            }
        }
        catch (NoSuchElementException e) {
            System.out.println("Error reading data: " + e.getMessage());
        }
    }
}

And lastly the RentShop class, which also has a readDetails method that is responsible for calling the readDetails method of the Car class and printing the values after storing them in an ArrayList.

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
import javax.swing.JFileChooser;

public class RentShop {
    // List used to store vehicles.
    public ArrayList<Vehicle> vehicleList;

    /**
     * Constructor for objects of class RentShop
     */
    public RentShop() {
        vehicleList = new ArrayList<Vehicle>();
    }

    /**
     * Storing vehicles.
     */
    public void storeVehicle(Vehicle vehicle) {
        vehicleList.add(vehicle);
    }

    /**
     * Printing the details about vehicle.
     */
    public void printAllVehicles() {
        for (Vehicle vehicle : vehicleList) {
            vehicle.printDetails();
        }
    }

    /**
     * Read the data.
     */
    public void readDetails() {
        // Create file dialog box to select input file
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setDialogTitle("Select Tool Data File");
        fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        fileChooser.setAcceptAllFileFilterUsed(false);
        fileChooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
        int result = fileChooser.showOpenDialog(null);
        if (result == JFileChooser.APPROVE_OPTION) {
            File selectedFile = fileChooser.getSelectedFile();
            try {
                // set up scanner to read from file
                Scanner scanner = new Scanner(selectedFile);
                while (scanner.hasNextLine()) {
                    String lineOfText = scanner.nextLine().trim();
                    System.out.println(lineOfText);

                    // create a second scanner to read tokens from lineOfText
                    Scanner scanner2 = new Scanner(lineOfText);
                    scanner2.useDelimiter(",");

                    // create a Vehicle object and add to vehicleList
                    Car car = new Car();
                    car.readDetails(scanner2);
                    vehicleList.add(car);

                    // close scanner2
                    scanner2.close();
                }

                // close scanner
                scanner.close();

                // print all vehicles
                printAllVehicles();
            }
            catch (FileNotFoundException e) {
                System.out.println("File not found: " + e.getMessage());
            }
        }
    }
}

My problem is, whenever I try running the readDetails method from the RentShop class, I want it to call for the readDetails method in the Car class, but it only reads and stores the data of the Vehicle class, and it ends up giving me false and 0 values for isConvertible and numOfDoors.

Now my goal is to make this work by having it call for the readDetails method in the Car class, which in turn calls for the readDetails method in the Vehicle class, thus having the values of both classes printed. The text file is well formatted so the problem isn't there.

I've been trying to solve this problem for the past three days, so any help or advice will be appreciated. (Also sorry in advance if this was poorly explained. This is my first time posting here.)

Edit: here is the data in the text file:

Mercedes-AMG,HJ7865,5,false,10900,345789,true,2
Nissan GT-R,MN6754,15,true,6700,574690,false,2
Toyota Camry,CB0054,13,true,5800,209856,true,4

I have plans to add other vehicles to the project later, so this is the data for the car.


Solution

  • I would remove the loops from the readDetails methods in class Vehicle and class Car, and read the details from the line scanner:

    Vehicle:

    public void readDetails(Scanner scanner) {
        vehicleModel = scanner.next().trim();
        vehicleCode = scanner.next().trim();
        timesRented = Integer.parseInt(scanner.next().trim());
        onRent = Boolean.parseBoolean(scanner.next().trim());
        price = Integer.parseInt(scanner.next().trim());
        vehiclePlateNum = Integer.parseInt(scanner.next().trim());
    }
    

    Car:

    @Override
    public void readDetails(Scanner scanner) {
        super.readDetails(scanner);
        this.isConvertible = Boolean.parseBoolean(scanner.next().trim());
        this.numOfDoors = Integer.parseInt(scanner.next().trim());
    }