【问题标题】:How to store the contents of this CSV file into an array of objects如何将此 CSV 文件的内容存储到对象数组中
【发布时间】:2021-04-04 10:35:22
【问题描述】:

我正在尝试制作一个 Java 程序,其中电视节目数据的 CSV 文件的内容存储在 TVShow 对象数组中。我让 TVShow 类对每个 CSV 文件的类别都有一个变量。

当我尝试跑步时,我不断收到NoSuchElementException。我尝试打印出文件的内容,它可以工作,但我不知道程序出了什么问题。

编辑: 根据@gthanop 的建议,我更改了下面的 Main.java 代码。现在的问题是数组的所有元素都是 CSV 文件的第一行。

这是 CSV 文件,然后是我的代码:

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]);
    }
  }
}

【问题讨论】:

  • 考虑使用 CSV 库而不是滚动您自己的 CSV 解析。
  • @MarkRotteveel 这是家庭作业的一部分,所以我不能使用外部库:(

标签: java arrays csv


【解决方案1】:

只需使用",|\n" 作为分隔符,因为行分隔符也用于分隔值。

例如:

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);
    }
}

注意:您确定作为构造参数调用的read2.next() 以所需的顺序执行吗?因为很久以前发生在我身上(我不记得使用哪种语言,很可能是 C++),序列与预期的完全相反......所以请确保按顺序读取 CSV 值( ie read-then-assign-to-variable) 然后构造你的TVShow 对象。就像上面的例子一样,我没有打电话:

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

而是:

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

更新 1:

在您更新后的代码中,您就快到了。只需像这样删除内部循环:

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]);
    }
  }
}

不过,在我看来,您可以从 Apache Commons CSV 或类似的库中获得更可靠的结果。

【讨论】:

  • 非常感谢!!新的分隔符帮助它编译,我应用了 toString 方法,然后尝试打印数组值。所以我猜while循环只能用CSV的第一行填充所有数组值:(
  • 基本上所有数组元素都由第一个 TVShow 对象组成,即使我尝试按顺序执行它(读取行,然后将 read.next() 分配给每个类别变量,并将它们放在新对象中)对于每个数组元素)
  • 没问题! :) ...while 循环仅设法用 CSV 的第一行填充所有数组值。 确实如此。至于read-then-assign,它的重点是不按行无序地读取 CSV 的列。当我测试它时,我发现实际上像您一样读取一行确实会产生所需的结果(即按顺序排列的列而不是交换它们),但为了安全起见,您可以 read-then-为每个不同的行分配,然后构造TVShow
  • 我为 Main.java 修改了上面的代码。你能看看吗?在我构建 TVShow 对象之前,我不太确定如何读取然后为每个不同的行分配。因为我假设 while 循环会构造多个对象,所以每行一个对象
  • 是的,第一个(外部)循环将逐行读取。然后在外部循环中,您将读取所有列(就像您正在做的那样)并创建一个 TVShow(您正在内部循环中执行此操作,这不是预期的)。根本不需要内部循环。只需将构造的TVShow 直接赋值给array[row],然后递增row。您可以在此答案中查看我的 Update 1 部分。
猜你喜欢
  • 2016-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-06
  • 2018-06-28
  • 2020-04-05
相关资源
最近更新 更多