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