Java如何解析和读取CSV文件

后端 潘老师 6个月前 (10-20) 181 ℃ (0) 扫码查看

CSV文件用于以纯文本形式存储表格数据。逗号分隔符用于标识和分隔CSV文件中的不同数据标记。

  • CSV(逗号分隔值)文件被消费者、企业和科学应用广泛使用。其最常见的用途是在运行时将表格数据从一个程序移动到另一个本地运行不兼容格式的程序。
  • CSV数据很流行,因为许多程序和语言都支持某种CSV变体,至少作为导入/导出的替代格式。

在Java中,有几种不同的方法可以读取和解析CSV文件。让我们讨论一些最佳方法:

1.使用OpenCSV库

OpenCSV是用于处理CSV文件的优秀库。它具有以下特性:

  • 每行读取任意数量的值
  • 在引用的元素中忽略逗号
  • 处理跨越多行的条目
  • 可配置的分隔符和引号字符
  • 一次性读取所有条目,或使用迭代器风格的模型

将OpenCSV的最新版本导入项目依赖项中。

<dependency>
  <groupId>net.sf.opencsv</groupId>
  <artifactId>opencsv</artifactId>
  <version>2.3</version>
</dependency>

示例1:将CSV文件逐行读取到String[]中

在给定的示例中,我们使用OpenCSV库中的CSVReader类,它包装了一个FileReader来读取实际的CSV文件。该文件使用逗号作为分隔符。

  • 使用reader.readNext(),我们逐行读取CSV文件。
  • 如果读取文件时发生错误,它将抛出IOException。
  • 如果读取的行不是有效的CSV字符串,它将抛出CsvValidationException。
  • 当所有行都被读取时,readNext()方法将返回null,程序终止。
try(CSVReader reader
        = new CSVReader(new FileReader("SampleCSVFile.csv")))
{
  String [] nextLine;
  //Read one line at a time
  while ((nextLine = reader.readNext()) != null)
  {
    //Use the tokens as required
    System.out.println(Arrays.toString(nextLine));
  }
}
catch (IOException | CsvValidationException e) {
  e.printStackTrace();
}

2.使用Super CSV库

Super CSV是Java中最先进、最快、最友好的免费CSV软件包。它支持很多有用的特性,例如:

  • 能够将数据读取和写入为POJO类
  • 自动编码和解码特殊字符
  • 自定义分隔符、引号字符和行分隔符
  • 支持单元格处理器以特定方式处理每个标记
  • 能够应用一个或多个约束,例如数字范围、字符串长度或唯一性
  • 能够处理来自文件、字符串、流甚至是zip文件的CSV数据

将Super CSV的最新版本添加到项目中。

<dependency>
  <groupId>net.sf.supercsv</groupId>
  <artifactId>super-csv</artifactId>
  <version>2.4.0</version>
</dependency>

示例2:将CSV文件读取到POJO

我们将读取以下CSV文件。

CustomerId,CustomerName,Country,PinCode,Email
10001,Lokesh,India,110001,abc@gmail.com
10002,John,USA,220002,def@gmail.com
10003,Blue,France,330003,ghi@gmail.com

相应的POJO类是:

public class Customer
{
  private Integer CustomerId;
  private String CustomerName;
  private String Country;
  private Long PinCode;
  private String Email;
}

请记住,列名应该与bean的字段名完全匹配,并且bean为每个字段定义了适当的setter。

import java.io.FileReader;
import java.io.IOException;
import org.supercsv.cellprocessor.Optional;
import org.supercsv.cellprocessor.ParseInt;
import org.supercsv.cellprocessor.ParseLong;
import org.supercsv.cellprocessor.constraint.NotNull;
import org.supercsv.cellprocessor.constraint.StrRegEx;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.CsvBeanReader;
import org.supercsv.io.ICsvBeanReader;
import org.supercsv.prefs.CsvPreference;
public class ReadCSVFileExample {
  static final String CSV_FILENAME = "data.csv";
  public static void main(String[] args) throws IOException
  {
    try(ICsvBeanReader beanReader
         = new CsvBeanReader(new FileReader(CSV_FILENAME), CsvPreference.STANDARD_PREFERENCE))
    {
      // the header elements are used to map the values to the bean
      final String[] headers = beanReader.getHeader(true);
      //final String[] headers = new String[]{"CustomerId","CustomerName","Country","PinCode","Email"};
      final CellProcessor[] processors = getProcessors();
      Customer customer;
      while ((customer = beanReader.read(Customer.class, headers, processors)) != null) {
        System.out.println(customer);
      }
    }
  }
  /**
   * Sets up the processors used for the examples.
   */
  private static CellProcessor[] getProcessors() {
    final String emailRegex = "[a-z0-9\\._]+@[a-z0-9\\.]+";
    StrRegEx.registerMessage(emailRegex, "must be a valid email address");
    final CellProcessor[] processors = new CellProcessor[] {
        new NotNull(new ParseInt()), // CustomerId
        new NotNull(), // CustomerName
        new NotNull(), // Country
        new Optional(new ParseLong()), // PinCode
        new StrRegEx(emailRegex) // Email
    };
    return processors;
  }
}

3.使用java.util.Scanner

Scanner类使用指定的分隔符模式将其输入分解为标记。默认分隔符是空格。

  • 我们可以使用单独的Scanner来读取行,而另一个Scanner用于将每行解析为标记。这种方法对于大型文件可能没有用,因为它每行创建一个Scanner实例。
  • 我们可以使用逗号作为分隔符来解析CSV文件。
  • 然后,可以使用各种next()方法将CSV标记转换为不同数据类型的值。

示例3:使用Scanner解析CSV文件

try(Scanner scanner = new Scanner(new File("SampleCSVFile.csv"))){
  //Read line
  while (scanner.hasNextLine()) {
    String line = scanner.nextLine();
    //Scan the line for tokens
    try (Scanner rowScanner = new Scanner(line)) {
      rowScanner.useDelimiter(",");
      while (rowScanner.hasNext()) {
        System.out.print(scanner.next());
      }
    }
  }
} catch (FileNotFoundException e) {
  e.printStackTrace();
}

4.使用BufferedReader和String.split()

在本方法中,我们使用BufferedReader逐行读取文件。然后使用String.split()函数根据作为方法参数提供的分隔符从当前行获取标记。

这种方法对于小字符串或小文件很有用。

示例4:拆分CSV字符串或CSV文件

在给定示例中,我们逐行读取文件。然后将每行拆分为逗号分隔的标记。

try(BufferedReader fileReader
        = new BufferedReader(new FileReader("SampleCSVFile.csv")))
{
  String line = "";

  //Read the file line by line
  while ((line = fileReader.readLine()) != null)
  {
    //Get all tokens available in line
    String[] tokens = line.split(",");

    //Verify tokens
    System.out.println(Arrays.toString(tokens));
  }
}
catch (IOException e) {
  e.printStackTrace();
}

5.结论

在Java中,使用许多方法都可以读取CSV文件。由于Java没有直接针对CSV处理的专用API,我们可以依靠SuperCSV等非常易于使用且高度可配置的开源库。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/back/10171.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】