使用commons-csv简单读写CSV文件

Posted 叶莜落

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用commons-csv简单读写CSV文件相关的知识,希望对你有一定的参考价值。

文章首发于我的github博客

需求

客户的开发测试环境将做迁移。因此需要对zookeeper上的重要的数据以CSV文件格式做备份。
本文通过Apache的commons-csv操作CSV文件。官网地址:http://commons.apache.org/proper/commons-csv/

基本概念

维基百科对CSV的解释:

逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须象二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。

代码

API使用很简单,直接上代码了。

  • 依赖包:

    <properties>
        <slf4j.version>1.7.2</slf4j.version>
        <log4j.version>1.2.17</log4j.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-csv</artifactId>
            <version>1.5</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
    </dependencies>
  • 配置文件csv.properties:

    # csv file output path(write)
    csvfile.output.path=D:/zk-backup/zk-privilige.csv
    # csv file input path(read)
    csvfile.input.path=D:/zk-backup/zk-privilige.csv
    #csvfile.input.path=/opt/apps/zk-recovery/zk-privilige.csv
    # csv header,使用逗号分隔
    csv.header=id,name,designation,company
  • 工具类:

① CSVWriter.java

package com.yeyouluo.csv.util;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.log4j.Logger;

/**
 * 写CSV工具类
 * @author yeyouluo
 *
 */
public class CSVWriter {

    private static final Logger logger = Logger.getLogger(CSVWriter.class);

    /**
     * 写CSV文件
     * @param csvFile csv文件名称
     * @param fileHeader 文件头
     * @param content 内容
     * @throws IOException
     */
    public static void write(final String csvFile, final String[] fileHeader, List<String[]> content)
            throws IOException {
        BufferedWriter writer = Files.newBufferedWriter(Paths.get(csvFile));
        CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.DEFAULT.withHeader(fileHeader));

        for (String[] c : content) {
            csvPrinter.printRecord(Arrays.asList(c));
        }
        csvPrinter.flush();
        logger.info( "====> 成功写入CSV文件。文件路径:" + csvFile );

    }
}

②CSVReaderWithlHeader.java

package com.yeyouluo.csv.util;

import java.io.IOException;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;

/**
 * 读带文件头的CSV文件工具类
 * @author yeyouluo
 *
 */
public class CSVReaderWithlHeader {
    /**
     * 
     * @param csvFile    CSV文件
     * @param fileHeader  CSV文件头
     * @param skipHeader  是否跳过文件头
     * @return              CSV记录链表
     * @throws IOException
     */
    public static List<CSVRecord> read(final String csvFile, final String[] fileHeader, boolean skipHeader)
            throws IOException {
        CSVFormat format;

        if (skipHeader) {
            // 这里显式地配置一下CSV文件的Header,然后设置跳过Header(要不然读的时候会把头也当成一条记录)
            format = CSVFormat.DEFAULT.withHeader(fileHeader).withFirstRecordAsHeader().withIgnoreHeaderCase()
                    .withTrim();
            // format = CSVFormat.DEFAULT.withHeader(fileHeader)
            // .withIgnoreHeaderCase().withTrim().withSkipHeaderRecord();
        } else {
            format = CSVFormat.DEFAULT.withHeader(fileHeader).withIgnoreHeaderCase().withTrim();
        }
        Reader reader = Files.newBufferedReader(Paths.get(csvFile));

        CSVParser csvParser = new CSVParser(reader, format);
        return csvParser.getRecords();
    }
    
    /**
     * 读取CSV文件,默认跳过文件头
     * @param csvFile    CSV文件
     * @param fileHeader  CSV文件头
     * @return          CSV记录链表
     * @throws IOException
     */
    public static List<CSVRecord> read(final String csvFile, final String[] fileHeader)
            throws IOException{
        return read(csvFile, fileHeader, true);
    }

}
  • 测试类

① CSVWriteService.java

package com.yeyouluo.csv.service;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.log4j.Logger;

import com.yeyouluo.csv.util.CSVWriter;

/**
 * 写CSV
 * @author yeyouluo
 *
 */
public class CSVWriteService {
    private static final Logger logger = Logger.getLogger(CSVWriter.class);

    private static String csvFile;  // csv文件路径
    
    private static String[] fileHeader;  // csv文件头

    static {
        // 读取配置文件
        Properties prop = new Properties();
        InputStream in = CSVWriter.class.getResourceAsStream("/csv.properties");
        try {
            prop.load(new InputStreamReader(in,"UTF-8"));
            String root = CSVWriter.class.getResource("/").getPath();
            csvFile = prop.getProperty("csvfile.output.path");
            String headers = prop.getProperty("csv.header");
            fileHeader = headers.split(",");
        } catch (Exception e) {
            logger.error("",e);
        } finally {
            if( in != null ) {
                try {
                    in.close();
                } catch (IOException e) {
                    logger.error("",e);
                }
            }
        }
        
        // 创建父目录
        File parentDir = new File(csvFile).getParentFile();
        if( !parentDir.exists() ) {
            logger.warn("CSV文件父目录不存在,即将创建...");
            parentDir.mkdirs();
        }
    }
    
    public void wirte(List<String[]> content) {
        try {
            CSVWriter.write(csvFile, fileHeader, content);
        } catch (IOException e) {
            logger.error("写CSV文件出现问题",e);
        }
    }
    
    public static void main(String[] args) {
        List<String[]> list = new ArrayList<String[]>();
        list.add(new String[] {"1", "Sundar Pichai ?", "CEO", "Google"});
        list.add(new String[] {"2", "Satya Nadella", "CEO", "Microsoft"});
        list.add(new String[] {"3", "Tim cook", "CEO", "Apple"});
        list.add(new String[] {"4", "Mark Zuckerberg", "CEO", "Facebook"});
        
        CSVWriteService csvWriteService = new CSVWriteService();
        csvWriteService.wirte(list);
    }
}

②CSVReaderWithlHeaderService.java

package com.yeyouluo.csv.service;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Properties;

import org.apache.commons.csv.CSVRecord;
import org.apache.log4j.Logger;

import com.yeyouluo.csv.util.CSVReaderWithlHeader;

/**
 * 读CSV
 * @author yeyouluo
 *
 */
public class CSVReaderWithlHeaderService {

    private static final Logger logger = Logger.getLogger(CSVReaderWithlHeaderService.class);

    private static String csvFile;  // csv文件路径
    
    private static String[] fileHeader;  // csv文件头

    static {
        // 读取配置文件
        Properties prop = new Properties();
        InputStream in = CSVReaderWithlHeaderService.class.getResourceAsStream("/csv.properties");
        try {
            prop.load(new InputStreamReader(in,"UTF-8"));
            String root = CSVReaderWithlHeaderService.class.getResource("/").getPath();
            csvFile = prop.getProperty("csvfile.input.path");
            String headers = prop.getProperty("csv.header");
            fileHeader = headers.split(",");
        } catch (Exception e) {
            logger.error("",e);
        } finally {
            if( in != null ) {
                try {
                    in.close();
                } catch (IOException e) {
                    logger.error("",e);
                }
            }
        }
        
        // 创建父目录
        File parentDir = new File(csvFile).getParentFile();
        if( !parentDir.exists() ) {
            logger.warn("CSV文件父目录不存在,即将创建...");
            parentDir.mkdirs();
        }
    }
    
    
    public void read() {
        try {
            List<CSVRecord> list =  CSVReaderWithlHeader.read(csvFile, fileHeader);
            for (CSVRecord csvRecord : list) {
                // Accessing values by the names assigned to each column

                String id = csvRecord.get("ID");
                String name = csvRecord.get("Name");
                String designation = csvRecord.get("Designation");
                String company = csvRecord.get("Company");

                System.out.println("Record No - " + csvRecord.getRecordNumber());
                System.out.println("---------------");
                System.out.println("ID : " + id);
                System.out.println("Name : " + name);
                System.out.println("Designation : " + designation);
                System.out.println("Company : " + company);
                System.out.println("---------------\n\n");
            }
        } catch (IOException e) {
            logger.error("读取CSV文件出现错误",e);
        }
    }
    
    public static void main(String[] args) {
        CSVReaderWithlHeaderService service = new CSVReaderWithlHeaderService();
        service.read();
    }

}

执行结果

  • 执行CSVWriteService.java
2018-03-03 11:05:43,551 [main] WARN  [com.yeyouluo.csv.util.CSVWriter] - CSV文件父目录不存在,即将创建...
2018-03-03 11:05:43,590 [main] INFO  [com.yeyouluo.csv.util.CSVWriter] - ====> 成功写入CSV文件。文件路径:D:/zk-backup/zk-privilige.csv
  • 执行CSVReaderWithlHeaderService.java
Record No - 1
---------------
ID : 1
Name : Sundar Pichai ?
Designation : CEO
Company : Google
---------------

Record No - 2
---------------
ID : 2
Name : Satya Nadella
Designation : CEO
Company : Microsoft
---------------

Record No - 3
---------------
ID : 3
Name : Tim cook
Designation : CEO
Company : Apple
---------------

Record No - 4
---------------
ID : 4
Name : Mark Zuckerberg
Designation : CEO
Company : Facebook
---------------

源码打包下载

链接: https://pan.baidu.com/s/1qZZru2K 密码: 866h

参考网址

以上是关于使用commons-csv简单读写CSV文件的主要内容,如果未能解决你的问题,请参考以下文章

Groovy学习笔记读取CSV文件

使用apache commons csv解析del(类似csv)格式文件

基于 java 注解的 csv 读写框架更加简单灵活

Java 导出 CSV 文件

(54)C#里简单地读写CSV文件

(54)C#里简单地读写CSV文件