使用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

参考网址

posted @ 2018-03-03 11:20  叶莜落  阅读(4664)  评论(0编辑  收藏  举报