0

I am new to java and practicing processing csv file. I've already successfully parsed the csv file, saved it in an array, and got rid of the header.

The file looks like this:

class, gender, age, bodyType, profession, pregnant, species, isPet, role
scenario:green,   ,         ,           ,         ,        ,      ,
person, female, 24, average , doctor    , FALSE   ,        ,      , passenger
animal, male  ,  4          ,           , FALSE   , dog    , true , pedestrian
  .
  .

the column without a string is empty in the file. Like the species and isPet above.

Now, I want to iterate through this array and create the instance, and it's too complex for me to figure it out.

For example, I have a Scenario class with the constructor:

Scenario(ArrayList<Character> passenger, ArrayList<Character> pedestrian, boolean greenOrRed)

and before creating scenario instance, I have to create Character by the constructor with two different subclasses Person and Animal. Further, arrange them into two separate groups, which are passenger and pedestrian:

Person(Gender gender, int age, Profession profession, BodyType bodyType, boolean isPregnant)
Animal(Gender gender, int age, BodyType bodyType, String species)

What I've tried like this:

public void loadCsv() throws IOException {

    String csvFile = "config.csv";
    String line = "";
    String csvSplit = ",";
    try (BufferedReader csvReader = new BufferedReader(new FileReader(csvFile));) {
        String headerLine = csvReader.readLine();
        while ((line = csvReader.readLine()) != null) {
            for (String token : data) {
                if (!token.isEmpty() && token.equals("scenario:green")) {
                    scenario.setLegalCrossing(true); //pass to setter works
                    //how to process with next token?
                }
            }
        }

    } catch (FileNotFoundException e) {
        e.printStackTrace();
        return;
    }

}

And I've referred to this post: How to easily process CSV file to List<MyClass>

Any help or hint is highly appreciated.

EDIT

The order is like this:

First, set the boolean greenOrRed from the Scenario class.

//if the class equals to Scenario:green
setLegalCrossing(true);

Second is to generate Person and Animal

//if class equals to Person
Person people =Person(Gender gender, int age, Profession profession, BodyType bodyType, boolean isPregnant)
//if class equals to Animal
Animal animal = Animal(Gender gender, int age, BodyType bodyType, String species)

Third, add them into superclass array:

ArrayList<Character> passenger = new ArrayList<Character>();
ArrayList<Character> pedestrian = new ArrayList<Character>();

passenger.add(people); // if role equals passenger
pedestrian.add(animal); // if role equals pedestrian

Finally, add passenger and pedestrian into Scenario constructor with the first step boolean value to form an instance.

Scenario singleScenario = Scenario(passenger, pedestrian, legalCrossing)
Woden
  • 1,054
  • 2
  • 13
  • 26
  • 1
    As per the answers on the ticket you mentioned, you could look into using a third party library such as opencsv. – mohammedkhan Jun 10 '20 at 14:39
  • I am trying not to using a third-party library if possible. But thank you for reviewing the question. @mohammedkhan – Woden Jun 10 '20 at 14:46
  • 1
    It is not quite clear how you should parse the cvs containing data for different classes. For example, if you have column `role`, it should be also separated with commas from empty columns `species` and `isPet`. – Nowhere Man Jun 10 '20 at 14:50
  • @AlexRudenko Thank you for pointing out. The actual file is with commas. Now, I am trying to deal with the array... – Woden Jun 10 '20 at 15:00
  • 1
    It is very likely that you need to provide [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example), and clarify which actual problem you're having now: how to split the line into fields, how create instances of Scenario, Person, Animal (as well as Gender, BodyType, Profession), what to do with pedestrian or passenger roles and whether apply them to Animal, etc. – Nowhere Man Jun 10 '20 at 15:16
  • @AlexRudenko Thank you. I've put the order of how these things work together. – Woden Jun 10 '20 at 15:39

1 Answers1

1

Please review the following example of parsing your sample data (all details of reading the CSV file and skipping the header are omitted):

List<String> csvContents = Arrays.asList(
//  "class, gender, age, bodyType, profession, pregnant, species, isPet, role",
    "scenario:green",
    "person, female, 24, average , doctor    , FALSE   ,        ,      , passenger",
    "animal, male  ,  4,         ,           , FALSE   , dog    , true , pedestrian"
);

Scenario scenario = null;
List<Character> passengers = new ArrayList<>();
List<Character> pedestrians = new ArrayList<>();

for (String line : csvContents) {
    String[] data = line.split("\\s*,\\s*"); // split by comma and remove redundant spaces
    Character character = null;
    String clazz = data[0].toLowerCase();
    if (clazz.startsWith("scenario")) {
        scenario = new Scenario();
        scenario.setLegalCrossing(clazz.endsWith("green"));
        continue;
    } else if ("person".equals(clazz)) {
        character = new Person(data[1], Integer.parseInt(data[2]), data[3], data[8], data[4], Boolean.parseBoolean(data[5]));
    } else if ("animal".equals(clazz)) {
        character = new Animal(data[1], Integer.parseInt(data[2]), data[3], data[8], data[6], Boolean.parseBoolean(data[7]));
    }

    String role = data[8].toLowerCase();
    if ("passenger".equals(role)) {
        if (null != character) passengers.add(character);
    } else if ("pedestrian".equals(role)) {
        if (null != character) pedestrians.add(character);
    }
}

System.out.println("passengers: " + passengers);
System.out.println("pedestrians: " + pedestrians);

if (null != scenario) {
    scenario.setPassengers(passengers);
    scenario.setPedestrians(pedestrians);
}

Output:

passengers: [Person(super=Character(gender=female, age=24, bodyType=average, role=passenger), profession=doctor, isPregnant=false)]
pedestrians: [Animal(super=Character(gender=male, age=4, bodyType=, role=pedestrian), species=dog, isPet=true)]

You should be able to use this code snippet as a reference and modify it according to your needs.

Nowhere Man
  • 19,170
  • 9
  • 17
  • 42
  • 1
    It's quite ok to [use enum's `valueOf(String)` method to convert string to enum](https://stackoverflow.com/questions/604424/how-to-get-an-enum-value-from-a-string-value-in-java). If `Gender`. `Role`, `BodyType`, etc. are enums, you should this method too. Or you can implement additional static method in these enums to iterate through `Enum.values()` and find appropriate instance by String parameter. – Nowhere Man Jun 11 '20 at 06:04
  • Thank you, sir. I've figured it out how to append it as an argument. – Woden Jun 11 '20 at 09:36
  • 1
    Yeah, btw you should not have replaced my split with this `csvLine.split(",",-1)` because you'd have to call `trim()` additionally on each element of the array – Nowhere Man Jun 11 '20 at 14:31