B.Mack B.Mack - 1 month ago 20
Java Question

Reading vehicles from a text file line by line and passing those vehicles into a constructor in Java

I'm new to Java, and I have an assignment to read vehicles from a text file line by line then stop at specific vehicles like (vehicle, car, truck, bicycle, american car, and foreign car) take the lines after those vehicles and pass them into a construct to convert the vehicles into objects so I can put those objects into an array. The vehicles will be extended from each other and in a specific layout in a text file. I'm having trouble figuring out a way to pass those lines into a constructor and returning the objects from the constructor. Here is an example of the text file layout.

vehicle
owner's name (string)
address (string)
phone (string)
email (string)

car - extends of vehicle
owner's name (string)
address (string)
phone (string)
email (string)
true or false for convertible (boolean)
color (string)

american car - extends of car
owner's name (string)
address (string)
phone (string)
email (string)
true or false for convertible (boolean)
color (string)
true or false for made in Detroit (boolean)
true or false for union shop (boolean)

foreign car - extends of car
owner's name (string)
address (string)
phone (string)
email (string)
true or false for convertible (boolean)
color (string)
country of manufacturer (string)
import duty (float)

bicycle - extends of vehicle
owner's name (string)
address (string)
phone (string)
email (string)
number of speeds (int)

truck - extends of vehicle
owner's name (string)
address (string)
phone (string)
email (string)
number of tons (float)
cost of truck (float)
date purchased (format below in example)


Also, here is the sample data I am using:

foreign car
aMarioy
Mario's house
(777) 777-7777
gmario@mario.com
false
black
Italy
4415.91

truck
aDougy
Doug's house
(123) 456-7890
hdoug@doug.com
30
61234.56
8/10/2003

vehicle
aRobby
Rob's house
(987) 654-3210
irob@rob.com

bicycle
bTommy
Tom's house
(246) 810-1214
jtom@tom.com
7

truck
bGeorge
George's house
(666) 666-6666
kgeorge@george.com
25
51234.56
12/4/2004

vehicle
bTim
Tim's house
(111) 111-1111
tim@tim.com

bicycle
bJim
Jim's house
(555) 555-5555
Ajim@jim.com
5

american car
bJohn
John's house
(888) 888-8888
Bjohn@john.com
true
green
false
true

car
cKen
Ken's house
(999) 999-9999
Cken@ken.com
false
orange

foreign car
cMario
Mario's house
(777) 777-7777
Dmario@mario.com
false
black
Italy
4415.91

truck
zDoug
Doug's house
(123) 456-7890
Edoug@doug.com
30
61234.56
8/10/2003

vehicle
eRob
Rob's house
(987) 654-3210
Frob@rob.com

bicycle
fTom
Tom's house
(246) 810-1214
Gtom@tom.com
7

american car
gSam
Sam's house
(333) 333-3333
Hsam@sam.com
false
blue
true
false





Here is my code...

import java.io.FileNotFoundException;
import java.util.Scanner;
import java.io.File;
import java.util.ArrayList;

public class test4{
public static void main(String[] args)throws FileNotFoundException {
try{
Scanner file = new Scanner(new File(args[0]));
//ArrayList<Vehicle> vehicleList = new ArrayList<>();
String line = new String();
String newLine = new String();
ArrayList<String> s1List = new ArrayList<>();
ArrayList<String> s2List = new ArrayList<>();
ArrayList<String> s3List = new ArrayList<>();
ArrayList<String> s4List = new ArrayList<>();
ArrayList<String> s5List = new ArrayList<>();
ArrayList<String> s6List = new ArrayList<>();

while(file.hasNextLine()){
line = file.nextLine();
if(line.equals("vehicle")){
while(file.hasNextLine()){
newLine = file.nextLine();
if(!(newLine.equals(""))){
s1List.add(newLine);
}
if(newLine.equals("")){
break;
}
}
}
if(line.equals("truck")){
while(file.hasNextLine()){
newLine = file.nextLine();
s2List.add(newLine);
if(newLine.equals("")){
break;
}
}
}
if(line.equals("bicycle")){
while(file.hasNextLine()){
newLine = file.nextLine();
s3List.add(newLine);
if(newLine.equals("")){
break;
}
}
}
if(line.equals("car")){
while(file.hasNextLine()){
newLine = file.nextLine();
s4List.add(newLine);
if(newLine.equals("")){
break;
}
}
}
if(line.equals("american car")){
while(file.hasNextLine()){
newLine = file.nextLine();
s5List.add(newLine);
if(newLine.equals("")){
break;
}
}
}
if(line.equals("foreign car")){
while(true){
newLine = file.nextLine();
s6List.add(newLine);
if(newLine.equals("")){
break;
}
}
}
}
/*
String[] s1 = s1List.toArray(new String[0]);
String[] s2 = s2List.toArray(new String[0]);
String[] s3 = s3List.toArray(new String[0]);
String[] s4 = s4List.toArray(new String[0]);
String[] s5 = s5List.toArray(new String[0]);
String[] s6 = s6List.toArray(new String[0]);
*/

/*
System.out.println(s1.length);


for(String a: s1){
System.out.println(a);
}
*/


/*
for(String a: s1List){
System.out.println(a);
}
for(String a: s2List){
System.out.println(a);
}
for(String a: s3List){
System.out.println(a);
}
for(String a: s4List){
System.out.println(a);
}
for(String a: s5List){
System.out.println(a);
}
for(String a: s6List){
System.out.println(a);
}
*/



}catch(FileNotFoundException ex){
System.out.println("File not found.");
}
}
public boolean equals(Object o){
if(this == o){
return true;
}
if(o == null){
return false;
}
return false;
}
}


class Vehicle{
private String owner = new String();
private String address = new String();
private String phone = new String();
private String email = new String();

public Vehicle(String[] strArr){
owner = strArr[0];
address = strArr[1];
phone = strArr[2];
email = strArr[3];
}
}


I currently have the program scanning the text file for vehicles then storing the sequential lines into an arraylists stopping at empty lines. I'm not sure how to pass specific indexes from an arraylist into constructors, because I was thinking that since the vehicles are always going to be in a specific layout but different order. I can count indexes in an arraylist to figure out what I can pass into a constructors.

Thanks for any help.

Answer

Any chance you can convert your input file into a CSV? Will be much easier to read and parse...

https://www.mkyong.com/java/how-to-read-and-parse-csv-file-in-java/

Then you can simply read a single line and have all of the data for that vehicle/car/truck/whatever you need to pass to the constructor.

Edit If not, I would do something close to the following. Note - this is in C#, but the same can be done in Java.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VehicleParsing
{
    class Program
    {
        static void Main(string[] args)
        {
            // Will maintain the string in the current line
            string line;

            // Contains the vehicles
            List<Vehicle> vehicles = new List<Vehicle>();

            // Contains all properties associated with the current vehicle being looked at
            List<string> currentVehicleData = new List<string>();

            // Read the file and display it line by line.
            System.IO.StreamReader file = new System.IO.StreamReader("C:/Users/Timot/Desktop/vehiclesample.txt");
            while ((line = file.ReadLine()) != null)
            {
                // Indicates we have read in all properties of the current vehicle
                if(String.IsNullOrEmpty(line))
                {
                    string vehicleType = currentVehicleData[0];
                    switch (vehicleType)
                    {
                        case "foreign car":
                            vehicles.Add(new ForeignCar(currentVehicleData));
                            break;
                        case "truck":
                            vehicles.Add(new Truck(currentVehicleData));
                            break;
                        case "vehicle":
                            vehicles.Add(new Vehicle(currentVehicleData));
                            break;
                        case "bicycle":
                            vehicles.Add(new Bicycle(currentVehicleData));
                            break;
                        case "american car":
                            vehicles.Add(new AmericanCar(currentVehicleData));
                            break;
                        case "car":
                            vehicles.Add(new Car(currentVehicleData));
                            break;
                        default:
                            throw new NotImplementedException();
                    }

                    currentVehicleData = new List<string>();
                }

                // Indicates the current vehicle's data is still being read
                else
                {
                    currentVehicleData.Add(line);
                }
            }

            file.Close();
        }
    }
}

And in Java:

package com.company;

import sun.reflect.generics.reflectiveObjects.NotImplementedException;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        // Holds the list of all vehicles found in the file
        ArrayList<Vehicle> vehicles = new ArrayList<Vehicle>();

        // Holds the data associated with the current vehicle being read
        ArrayList<String> currentVehicleData = new ArrayList<String>();

        // Java knowledge lacking here - not certain why I can't simply let the FNF exception bubble up
        Scanner file = null;
        try {
            file = new Scanner(new File("C:/Users/Timot/Desktop/vehiclesample.txt"));
        } catch(FileNotFoundException fnfe) {
            // Do something with this exception
            return;
        }

        String line;
        while(file.hasNextLine()) {
            // Get next line
            line = file.nextLine();

            // Next line is empty, so currentVehicleData has all the data associated the current vehicle
            if(line.isEmpty()) {
                String vehicleType = currentVehicleData.get(0);
                switch(vehicleType) {
                    case "foreign car":
                        vehicles.add(new ForeignCar(currentVehicleData));
                        break;
                    case "truck":
                        vehicles.add(new Truck(currentVehicleData));
                        break;
                    case "vehicle":
                        vehicles.add(new Vehicle(currentVehicleData));
                        break;
                    case "bicycle":
                        vehicles.add(new Bicycle(currentVehicleData));
                        break;
                    case "american car":
                        vehicles.add(new AmericanCar(currentVehicleData));
                        break;
                    case "car":
                        vehicles.add(new Car(currentVehicleData));
                        break;
                    default:
                        throw new NotImplementedException();
                }

                currentVehicleData = new ArrayList<String>();
            }

            // Still reading data for the current vehicle
            else {
                currentVehicleData.add(line);
            }
        }

        file.close();
    }
}