【问题标题】:OpenCSV: Method is returning null when reads the CSVOpenCSV:读取 CSV 时方法返回 null
【发布时间】:2021-10-14 04:47:14
【问题描述】:

在很长时间没有学习这门语言之后,我正在重新学习 Java 知识,并且我正在使用 OpenCSV for Java。我编写了一个读取具有以下结构的 CSV 文件的方法:

id,first_name,last_name,email,gender,ip_address,date
1,Bear,Picker,bpicker0@wordpress.com,Bigender,33.63.86.239,20/06/2021
2,Emili,McEntee,emcentee1@sciencedirect.com,Bigender,163.127.107.66,03/08/2021
3,Bethena,Fortune,bfortune2@live.com,Genderqueer,52.250.33.22,22/04/2021
4,Mortie,Praten,mpraten3@google.nl,Genderfluid,181.3.231.237,09/07/2021
5,Nappy,Giabucci,ngiabucci4@unc.edu,Female,110.180.139.101,01/06/2021

这是我写的读取文件的基本方法:

public static List<String> readDataLineByLine(String path, Class classModel) {
  try {
      Reader reader = Files.newBufferedReader(Paths.get(path));

      CsvToBean csvToBean = new CsvToBeanBuilder(reader)
              .withType(classModel)
              .withSeparator(',')
              .withSkipLines(1)
              .withIgnoreLeadingWhiteSpace(true)
              .build();

      List<String> results = csvToBean.parse();

      return results;
  } catch(IOException ex) {
      Log.error(ex.toString());
      return null;
  }
}

我的模型课:

public class MockarooFakeModel {

    @CsvBindByName(column = "id")
    private int ID;

    @CsvBindByName(column = "first_name")
    private String firstName;

    @CsvBindByName(column = "last_name")
    private String lastName;

    @CsvBindByName(column = "email")
    private String email;

    @CsvBindByName(column = "gender")
    private String gender;

    @CsvBindByName(column = "ip_address")
    private String IPAddress;

    @CsvBindByName(column = "date")
    private String date;

    public int getID() {
        return ID;
    }

    public void setID(int ID) {
        this.ID = ID;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getIPAddress() {
        return IPAddress;
    }

    public void setIPAddress(String IPAddress) {
        this.IPAddress = IPAddress;
    }

    public Date getDate() {
        try {
            Date date = new SimpleDateFormat("dd/MM/yyyy").parse(this.date);
            return date;
        } catch (ParseException ex) {
            Log.error(ex.toString());
            return null;
        }
    }

    public void setDate(String date) {
        this.date = date;
    }
}

由于某种原因,当我调试代码时,它返回 4 行而不是 5 行,并且还返回带有 null 的行。我认为这是因为我没有映射模型,但这并没有解决问题。另外,我不认为 TestNG 在我执行测试时会引起一些冲突。

@Test(description = "Gets the data stored in a CSV file")
public void Test4(Method method) {
    startTest(method.getName(),"Gets the data stored in a CSV file");

    var records = Utils.readDataLineByLine("PathToTheFile.csv", MockarooFakeModel.class);
}

如果能帮助我解决我的问题,我将不胜感激。谢谢!

更新

我忘记选中复选框来回答我自己的问题,但我把问题的解决方案留在这里(感谢@lastzolex)。-

我删除了.withSkipLines() 并更新了我的阅读器方法以返回Class

public static List<Class> readDataLineByLine(String path, Class classModel) {
    try {
        Reader reader = Files.newBufferedReader(Paths.get(path));

        CsvToBean csvToBean = new CsvToBeanBuilder(reader)
                .withType(classModel)
                .withSeparator(',')
                .withIgnoreLeadingWhiteSpace(true)
                .build();

        List<Class> results = csvToBean.parse();

        return results;
    } catch(IOException ex) {
        Log.error(ex.toString());
        return null;
    }
}

我不知道.withSkipLines() 跳过了我正在发送的数据行(我所做的映射是自动完成的)。

【问题讨论】:

    标签: java csv opencsv


    【解决方案1】:

    你把问题描述得很好,谢谢!

    在我看来,唯一的问题是线路

    .withSkipLines(1)
    

    因为您在同时映射标题时跳过了标题行。所以库无法匹配任何值。

    只需从 lambda 中删除它,您将获得 5 行正确映射的值。

    【讨论】:

    • 还有一件事:您读取 CSV 的方法应该返回“List”而不是“List
    • 最好编辑你的帖子来补充。
    • 感谢您的提示。我将来会这样做。为了解释我的意图:该评论与所述问题无关,它只是另一个提示,一般来说可以改进代码。所以我选择了评论而不是答案。
    • @LastZolex 我的想法是使用一种通用方法,该方法使用任何不同类型的模型,而不仅仅是我正在传递的模型。我怎样才能做到这一点?另一方面,如您所见,我的 CSV 文件中有 6 行,我跳过了标题。为什么它不返回 5 行,而不计算标题?
    • 好的,我明白了。但是,您正在寻找与您在此处绘制的解决方案完全不同的解决方案......再次总结一下:所描述方法的问题是您使用标题信息将 CSV 的每一行映射到一个对象实例。这是通过注解@CsvBindByName 完成的。但是你完全跳过了标题,所以库不能映射任何东西,因为它期望标题在文件的第 2 行......你对“csvToBean.parse()”行应该返回什么的期望到底是什么?
    猜你喜欢
    • 1970-01-01
    • 2022-11-12
    • 1970-01-01
    • 2013-03-08
    • 2017-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多