1

I'm trying to make a Java program where the contents of a CSV file of TV show data is stored in an array of TVShow objects. I made the TVShow class have a variable for each of the CSV file's categories.

When I try running, I keep getting a NoSuchElementException. I tried printing out the contents of the file and it worked, but I don't know what is wrong with the program.

Edit: After following advice of @gthanop, I changed the Main.java code below. The issue now is that all of the array's elements are the first row of the CSV file.

This is the CSV file, and then my code:
enter image description here

public class TVShow
{
  String name;
  String yearPremiered;
  String numOfSeasons;
  String numOfEpisodes;
  String network;
  String genre;
  String maleLead;
  String femaleLead;

  public TVShow(String name, String yearPremiered, String numOfSeasons, String numOfEpisodes, String network, String genre, String maleLead, String femaleLead)
  {
    this.name = name;
    this.yearPremiered = yearPremiered;
    this.numOfSeasons = numOfSeasons;
    this.numOfEpisodes = numOfEpisodes;
    this.network = network;
    this.genre = genre;
    this.maleLead = maleLead;
    this.femaleLead = femaleLead;
  } 
}
import java.io.*;
import java.util.Scanner;

public class Main
{
  public static void main(String[] args) throws Exception
  {
    TVShow[] array = new TVShow[20]; //There are 20 rows of TV show data in the CSV file

    Scanner read = new Scanner(new File("tv_shows.csv"));

    read.nextLine();

    int row = 0;

    read.useDelimiter(",|\n");

    while (read.hasNext())
    {
      String name = read.next();
      String yearPremiered = read.next();
      String numOfSeasons = read.next();
      String numOfEpisodes = read.next();
      String network = read.next();
      String genre = read.next();
      String maleLead = read.next();
      String femaleLead = read.next();

      while (row < 20)
      {
        array[row] = new TVShow(name, yearPremiered, numOfSeasons, numOfEpisodes, network, genre, maleLead, femaleLead);
        row++;
      }
    }

    read.close();

    for (int i = 0; i < 20; i++)
    {
      System.out.println(array[i]);
    }
  }
}
2
  • Consider using a CSV library instead of rolling your own CSV parsing. Commented Apr 4, 2021 at 11:26
  • @MarkRotteveel this is part of a homework assignment so I can't use external libraries :( Commented Apr 4, 2021 at 12:09

1 Answer 1

1

Just use ",|\n" as the delimiter, because line separators also separate values.

For example:

public class Main {
    private static class TVShow {
        private final String name;
        private final int number;

        public TVShow(final String name,
                      final int number) {
            this.name = name;
            this.number = number;
        }

        @Override
        public String toString() {
            return "{name = " + name + ", number = " + number + '}';
        }
    }

    public static void main(final String[] args) {
        final ArrayList<TVShow> shows = new ArrayList<>();
        try (final Scanner scan = new Scanner("a,0\nb,1\nc,2")) {
            scan.useDelimiter(",|\n");
            while (scan.hasNext()) {
                final String name = scan.next();
                final int number = scan.nextInt();
                shows.add(new TVShow(name, number));
            }
        }
        System.out.println(shows);
    }
}

Note: are you sure that the read2.next() called as the construction arguments are executed in the desired sequence? Because it happened to me once upon a time ago (I don't remember in which language though, most likely C++) that the sequence was exactly the opposite than the one intended... So make sure you read your CSV values in sequence (ie read-then-assign-to-variable) and then construct your TVShow object. Just like in the above example I am not calling:

shows.add(new TVShow(scan.next(), scan.nextInt()));

but instead:

final String name = scan.next();
final int number = scan.nextInt();
shows.add(new TVShow(name, number));

Update 1:

In your updated code, you are almost there. Just remove the inner loop like so:

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

public class Main
{
  public static void main(String[] args) throws Exception
  {
    TVShow[] array = new TVShow[20]; //There are 20 rows of TV show data in the CSV file

    Scanner read = new Scanner(new File("tv_shows.csv"));

    read.nextLine();

    int row = 0;

    read.useDelimiter(",|\n");

    while (read.hasNext())
    {
      String name = read.next();
      String yearPremiered = read.next();
      String numOfSeasons = read.next();
      String numOfEpisodes = read.next();
      String network = read.next();
      String genre = read.next();
      String maleLead = read.next();
      String femaleLead = read.next();

      array[row] = new TVShow(name, yearPremiered, numOfSeasons, numOfEpisodes, network, genre, maleLead, femaleLead);
      row++;
    }

    read.close();

    for (int i = 0; i < 20; i++)
    {
      System.out.println(array[i]);
    }
  }
}

In my opinion though, you can expect more robust results from a library like Apache Commons CSV or something similar.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks a lot!! The new delimiter helped it to compile, I applied the toString method and then tried printing the array values. So I guess the while loop only managed to fill all of the array values with the first row of the CSV :(
Basically all the array elements consist of the first TVShow object, even after I tried doing it in sequence (reading line, then assigning read.next() to each category variable, and placing them in new objects for each array element)
No problem! :) ...the while loop only managed to fill all of the array values with the first row of the CSV. yes indeed. As for the read-then-assign, the whole point of it is to not read the columns of the CSV out of order, per line. As I was testing it, I found out that actually reading a single line as you did, was indeed producing the desired results (ie columns in order instead of interchanging them), but just to be safe you can read-then-assign for each different line, and then construct the TVShow.
I revised the code above for Main.java. Can you take a look? I'm not quite sure how to approach reading then assigning for each different line, before I construct the TVShow objects. Since I assumed the while loop would construct multiple objects, well one for each line
Yes the first (outter) loop will read line-by-line. Then inside the outter loop you will read all columns (just like you are doing) and create a single TVShow (which you are doing inside the inner loop, which is not what intended). The inner loop is not needed at all. Just directly assign the constructed TVShow to array[row] and then increment row. You can have a look at my Update 1 section in this answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.