如何读写CSV文件-超级CSV教程

Java语言不提供任何本机支持来有效处理CSV文件。因此,我们将使用超级CSV读取CSV文件,并用Java编写一个新的CSV文件。

阅读更多:如何读写CSV – OpenCSV教程

目录

1.超级CSV maven依赖项
2.超级CSV通用类
3.如何读取CSV文件
4.如何部分读取CSV文件
5.如何在键值对
中读取CSV文件6.如何读取具有任意编号的CSV文件列
7。如何编写新的CSV文件

1.超级CSV Maven依赖项

让我们从列出在项目中使用Super CSV所需的Maven依赖关系开始。

pom.xml
  <modelVersion>4.0.0</modelVersion>
  <groupId>SuperCSVExamples</groupId>
  <artifactId>SuperCSVExamples</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
    <dependency>
        <groupId>net.sf.supercsv</groupId>
        <artifactId>super-csv</artifactId>
        <version>2.4.0</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.4</version>
    </dependency>
  </dependencies>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3.2</version>
        <configuration>
          <source>1.7</source>
          <target>1.7</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

如果您正在使用gradle build,请使用它。

'net.sf.supercsv:super-csv:2.4.0'
'org.slf4j:slf4j-api:1.7.4'

2.超级CSV通用类

让我们看一下在使用Super CSV读取或写入CSV文件时需要了解的主要类。

2.1。ICsvBeanReader和CsvBeanReader

ICsvBeanReader(接口)和CsvBeanReader(实现类)用于读取CSV文件。它通过实例化每行的bean并将每一列映射到bean上的字段来读取CSV文件。

要填充的bean可以是类或接口。如果使用了一个类,则它必须是有效的Java bean,即它必须具有默认的无参数构造函数和getter / setter方法。如果接口定义了getters / setter,那么也可以使用该接口–将创建一个实现该接口的代理对象。

2.2。ICsvBeanWriter和CsvBeanWriter

ICsvBeanWriter(接口)和CsvBeanWriter(实现类)用于写入CSV文件。它通过将bean上的每个字段映射到CSV文件中的一列(使用提供的名称映射)来编写CSV文件。

2.3。细胞处理器

CellProcessor实例用于从CSV文件读取值并对其进行处理,然后再将其设置为Java bean类/接口。例如,我们想要将值转换为Date对象,甚至您可能想对值运行一些正则表达式验证。

2.4。CsvPreference

在读取或写入CSV文件之前,必须为读取器/写入器提供一些首选项。从本质上讲,这意味着您正在CSV文件中设置与定界符相关的配置。例如CsvPreference.STANDARD_PREFERENCE意味着:

引号字符=“
分隔符=
行尾符号= \ r \ n

我们还可以创建您自己的首选项。例如,如果文件是管道分隔的,则可以使用以下内容:

private static final CsvPreference PIPE_DELIMITED = new CsvPreference.Builder('"''|', "\n").build();

3.如何读取CSV文件

现在,让我们看一个使用上述类读取CSV文件的示例。我将阅读以下给出的内容data.csv

data.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
10004,Reddy,Jermany,440004,abc@gmail.com
10005,Kumar,India,110001,def@gmail.com
10006,Paul,USA,220002,ghi@gmail.com
10007,Grimm,France,330003,abc@gmail.com
10008,WhoAmI,Jermany,440004,def@gmail.com
10009,Bharat,India,110001,ghi@gmail.com
10010,Rocky,USA,220002,abc@gmail.com
10011,Voella,France,330003,def@gmail.com
10012,Gruber,Jermany,440004,ghi@gmail.com
10013,Satty,India,110001,abc@gmail.com
10014,Bean,USA,220002,def@gmail.com
10015,Krish,France,330003,ghi@gmail.com
And we will be populating the instances of <code>Customer.java</code> with values of above file.
package com.how2codex.example;
public class Customer
{
    private Integer CustomerId;
    private String CustomerName;
    private String Country;
    private Long PinCode;
    private String Email;
    
    public Customer(){
    }
    
    public Customer(Integer customerId, String customerName, String country, Long pinCode, String email) {
        super();
        this.CustomerId = customerId;
        this.CustomerName = customerName;
        this.Country = country;
        this.PinCode = pinCode;
        this.Email = email;
    }
    
    //Getters and setters
    @Override
    public String toString() {
        return "Customer [CustomerId=" + CustomerId + ", CustomerName="
                + CustomerName + ", Country=" + Country + ", PinCode="
                + PinCode + ", Email=" + Email + "]";
    }
}

现在看CSV文件,第一行是列名。它们应与Bean的字段名完全匹配,并且Bean具有为每个字段定义的适当的设置方法。

如果标题不匹配(或没有标题),那么我们可以简单地定义自己的名称映射数组。[ 我已注解掉该行,但您可能会提示。]

ReadCSVFileExample.java
package com.how2codex.example;
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;
    }
}

程序输出。

安慰
Customer [CustomerId=10001, CustomerName=Lokesh, Country=India, PinCode=110001, Email=abc@gmail.com]
Customer [CustomerId=10002, CustomerName=John, Country=USA, PinCode=220002, Email=def@gmail.com]
Customer [CustomerId=10003, CustomerName=Blue, Country=France, PinCode=330003, Email=ghi@gmail.com]
//..。 So on

4.如何部分读取CSV文件

通过部分读取,我们只需将相应的标题列设置为即可在读取CSV文件时忽略列null。例如,在下面的代码中,我决定不读取PinCode列。

final String[] headers = new String[]{"CustomerId""CustomerName""Country"null"Email"};

4.1。完整的例子

PartialReadCSVFileExample.java
package com.how2codex.example;
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 PartialReadCSVFileExample {
    static final String CSV_FILENAME = "data.csv";
    public static void main(String[] args) throws IOException
    {
        final String emailRegex = "[a-z0-9\\._]+@[a-z0-9\\.]+";
        StrRegEx.registerMessage(emailRegex, "must be a valid email address");
        
        try(ICsvBeanReader beanReader = new CsvBeanReader(new FileReader(CSV_FILENAME), CsvPreference.STANDARD_PREFERENCE))
        {
            //First column is header
            beanReader.getHeader(true);
            //Set null for columns you do not want to read
            //final String[] headers = beanReader.getHeader(true);
            final String[] headers = new String[]{"CustomerId""CustomerName""Country"null"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;
    }
}

程序输出。

安慰
Customer [CustomerId=10001, CustomerName=Lokesh, Country=India, PinCode=null, Email=abc@gmail.com]
Customer [CustomerId=10002, CustomerName=John, Country=USA, PinCode=null, Email=def@gmail.com]
Customer [CustomerId=10003, CustomerName=Blue, Country=France, PinCode=null, Email=ghi@gmail.com]
//..。 So on

5.如何读取键值对中的CSV文件

要读入键值对,我们需要使用CsvMapReader。它使您可以按名称从生成的Map中检索各列,尽管您必须将各列转换为适当的类型。

ReadCSVFileInKeyValuePairs.java
package com.how2codex.example;
import java.io.FileReader;
import java.io.IOException;
import java.util.Map;
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.CsvMapReader;
import org.supercsv.io.ICsvMapReader;
import org.supercsv.prefs.CsvPreference;
public class ReadCSVFileInKeyValuePairs {
    static final String CSV_FILENAME = "data.csv";
    public static void main(String[] args) throws IOException
    {
        try(ICsvMapReader listReader = new CsvMapReader(new FileReader(CSV_FILENAME), CsvPreference.STANDARD_PREFERENCE))
        {
            //First Column is header names
            final String[] headers = listReader.getHeader(true);
            final CellProcessor[] processors = getProcessors();
            Map<String, Object> fieldsInCurrentRow;
            while ((fieldsInCurrentRow = listReader.read(headers, processors)) != null) {
                System.out.println(fieldsInCurrentRow);
            }
        }
    }
    /**
     * 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;
    }
}

程序输出。

安慰
{Country=India, CustomerId=10001, CustomerName=Lokesh, Email=abc@gmail.com, PinCode=110001}
{Country=USA, CustomerId=10002, CustomerName=John, Email=def@gmail.com, PinCode=220002}
{Country=France, CustomerId=10003, CustomerName=Blue, Email=ghi@gmail.com, PinCode=330003}
//..。 So on

6.如何读取任意列的CSV文件

某些CSV文件不符合RFC4180,每行的列数不同。如果您有这样的CSV文件,则需要使用CsvListReader,因为它是唯一支持它的阅读器。

读取此类文件非常棘手,因为您不知道任何行中的列数。因此,您要读取a中一行中的所有列,List然后根据列表的大小来确定如何处理读取的值。

让我们修改data.csv并从中随机删除一些数据。

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

让我们阅读此CSV文件。

ReadCSVFileWithArbitraryNumberOfColumns.java
package com.how2codex.example;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
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.CsvListReader;
import org.supercsv.io.ICsvListReader;
import org.supercsv.prefs.CsvPreference;
public class ReadCSVFileWithArbitraryNumberOfColumns {
    static final String CSV_FILENAME = "data.csv";
    public static void main(String[] args) throws IOException
    {
        try(ICsvListReader listReader = new CsvListReader(new FileReader(CSV_FILENAME), CsvPreference.STANDARD_PREFERENCE))
        {
            //First Column is header names- though we don't need it in runtime
            @SuppressWarnings("unused")
            final String[] headers = listReader.getHeader(true);
            CellProcessor[] processors = null;
            List<String> fieldsInCurrentRow;
            while ((fieldsInCurrentRow = listReader.read()) != null) {
                if(fieldsInCurrentRow.size() == 5){
                    processors = getFiveColumnProcessors();
                }else if(fieldsInCurrentRow.size() == 4) {
                    processors = getFourColumnProcessors();
                }else if(fieldsInCurrentRow.size() == 3) {
                    processors = getThreeColumnProcessors();
                }else{
                    //Create more processors
                }
                final List<Object> formattedFields = listReader.executeProcessors(processors);
                System.out.println(String.format("rowNo=%s, customerList=%s", listReader.getRowNumber(), formattedFields));
            }
        }
    }
    private static CellProcessor[] getFiveColumnProcessors() {
        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;
    }
    private static CellProcessor[] getFourColumnProcessors() {
        final CellProcessor[] processors = new CellProcessor[] {
                new NotNull(new ParseInt()), // CustomerId
                new NotNull(), // CustomerName
                new NotNull(), // Country
                new Optional(new ParseLong()) // PinCode
        };
        return processors;
    }
    private static CellProcessor[] getThreeColumnProcessors() {
        final CellProcessor[] processors = new CellProcessor[] {
                new NotNull(new ParseInt()), // CustomerId
                new NotNull(), // CustomerName
                new NotNull() //Country
        };
        return processors;
    }
}

程序输出。

安慰
rowNo=2, customerList=[10001, Lokesh, India, 110001, abc@gmail.com]
rowNo=3, customerList=[10002, John, USA]
rowNo=4, customerList=[10003, Blue, France, 330003]

7.如何编写新的CSV文件

编写CSV文件与读取CSV文件一样简单。创建CsvBeanWriter实例,定义标头和处理器并编写Bean。它将生成CSV文件,其中包含从bean中填充的数据值。

超级csv编写器示例

WriteCSVFileExample.java
package com.how2codex.example;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
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.CsvBeanWriter;
import org.supercsv.io.ICsvBeanWriter;
import org.supercsv.prefs.CsvPreference;
public class WriteCSVFileExample
{
    //Watch out for Exception in thread "main" java.lang.ExceptionInInitializerError
    private static List<Customer> customers = new ArrayList<Customer>();
    static
    {
        customers.add(new Customer(1"Lokesh""India", 12345L, "mobtrack_service@163.com"));
        customers.add(new Customer(2"Mukesh""India", 34234L, "mukesh@gmail.com"));
        customers.add(new Customer(3"Paul""USA", 52345345L, "paul@gmail.com"));
    }
    
    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;
    }
    
    public static void main(String[] args)
    {
        
        ICsvBeanWriter beanWriter = null;
        
        try
        {
            beanWriter = new CsvBeanWriter(new FileWriter("temp.csv"), CsvPreference.STANDARD_PREFERENCE);
            final String[] header = new String[] { "CustomerId""CustomerName""Country""PinCode" "Email" };
            final CellProcessor[] processors = getProcessors();
            // write the header
            beanWriter.writeHeader(header);
            // write the beans data
            for (Customer c : customers) {
                beanWriter.write(c, header, processors);
            }
        } catch (IOException e) {
            e.printStackTrace();
        finally {
            try {
                beanWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

以上程序的输出将被写入temp.csv以下文件中:

临时csv
CustomerId,CustomerName,Country,PinCode,Email
1,Lokesh,India,12345,howtodoinjava@gmail.com
2,Mukesh,India,34234,mukesh@gmail.com
3,Paul,USA,52345345,paul@gmail.com

这就是简单的用例,以及使用Super CSV 以各种方式读取和写入CSV文件的示例。

如果您有任何疑问,请在评论区留言,我会一一解答。

saigon has written 1445 articles

Leave a Reply