一: CSV简介
Comma-Separated Values(CSV), 因分隔符没有严格指定规范标准,可以使用逗号,也可以使用其他字符(如制表符\t、分号;等),所以CSV也称为 逗号分隔值或者字符分隔值。csv文件是使用纯文本来存储表格数据(即只能存储文本,不能存储二进制数据)。CSV因没有严格的规范,所以变异的形式比较多。
二: CSV文件的组成和规则
组成:
csv文件由任意条数据的【记录】组成, 每条记录的最后一个字段也要使用分隔符,记录间一般使用换行符分隔\n,也可以指定其他字符串(比如”——”)
每条记录由【字段】组成,字段间使用分隔符(逗号、制表符\t等)分隔。
规则:
- 开头是不留空,以行为单位。
- 可含或不含列名,含列名则居文件第一行。
- 一行数据不跨行,无空行。
- 以半角逗号(即,)作分隔符,列为空也要表达其存在。
- 列内容如存在半角引号(即”),替换成半角双引号(”“)转义,即用半角引号(即”“)将该字段值包含起来。
- 文件读写时引号,逗号操作规则互逆。
- 内码格式不限,可为 ASCII、Unicode 或者其他。
- 不支持特殊字符
- 如果值有特殊字符(逗号,双引号,换行符等)要使用引号(一般使用双引号,也可以指定单引号)括起来,比如分隔符是逗号,值中也出现逗号了
- 值中出现双引号,需要使用双引号来转义
三: CSV和Excel的区别
.csv文件可以被excel软件打开,csv只能用于存储纯文本内容,excel不仅支持纯文本内容还支持二进制数据,可以看做csv是excel的轻量级简单版的实现,excel比csv更加强大,csv文件一般用于表格数据的传输。
四:类库简介opencsv
官网:http://opencsv.sourceforge.net/
maven:https://mvnrepository.com/artifact/com.opencsv/opencsv
支持注解(根据名称或者位置)
支持自定义转换器AbstractBeanField
支持跳跃行skipLine和数据过滤Filter
注解:
@CsvBindByName:根据CSV输入中该字段的标题名,将一个bean字段映射到CSV文件中的一个字段, 可以控制列名,按名字列名的先后顺序好像是按照字母排序的
@CsvBindByPosition:根据CSV输入中字段的数字位置,将一个bean字段映射到CSV文件中的一个字段@CsvBindByPosition(position = 0) 按位置好像不能写列名,但是可以控制列的顺序, 还不知道即可控制列名,又可以控制列的顺序的方法(通过String[]控制应该是最灵活的)
@CsvCustomBindByName:与CsvBindByName相同,但必须提供自己的数据转换类。
@CsvCustomBindByPosition:与CsvBindByPosition相同,但必须提供自己的数据转换类。
@CsvDate:必须应用于日期/时间类型的bean字段,以便自动转换工作,并且必须与前述四个注释中的一个一起使用。
API
CSVWriter public CSVWriter(Writer writer, char separator, char quotechar, char escapechar, String lineEnd); public void writeAll(List allLines); public void writeNext(String[] nextLine); protected void writeColumnNames(ResultSet rs); public void flush(); public void close(); CSVReader public CSVReader(Reader reader, char separator, char quotechar, char escape, int line, boolean strictQuotes, boolean ignoreLeadingWhiteSpace); public String[] readNext(); public List readAll(); public void close(); Strategy ColumnPositionMappingStrategy HeaderColumnNameMappingStrategy HeaderColumnNameTranslateMappingStrategy
自定义的符号:
char separator: 分隔符, 默认使用逗号
char quotechar: 引号字符,双引号或者单引号,默认双引号,每个值都使用指定的引号包围起来,即使数据类型是int类型也会用引号引起来
char escapechar:转义字符, 默认是双引号
String lineEnd:行结束符,默认\n 或者 \r\n
五:基本使用
方式一:使用String[]方式
// CSVWriter 写 @Test public void testWriteByStringArray() throws Exception{ OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream("D:\\test.csv"), Charset.forName("UTF-8")); CSVWriter csvWriter = new CSVWriter(out, ','); String[] record0 = {"id", "name", "age", "birthday"}; csvWriter.writeNext(record0); String[] record1 = {"1", "张三", "20", "1990-08-08"}; String[] record2 = {"2", "lisi", "21", "1991-08-08"}; String[] record3 = {"3", "wangwu", "22", "1992-08-08"}; ListallLines = new ArrayList (); allLines.add(record1); allLines.add(record2); allLines.add(record3); csvWriter.writeAll(allLines); csvWriter.close(); }
// CSVReader 读 @Test public void testRead() throws Exception{ InputStreamReader in = new InputStreamReader(new FileInputStream("D:\\test.csv"), Charset.forName("UTF-8")); CSVReader reader = new CSVReader(in, ','); ListallRecords = reader.readAll(); for (String[] records : allRecords) { for (String filed : records) { System.out.print(filed + " "); } System.out.println(); } reader.close(); }
package com.mengday.csv; import com.opencsv.bean.*; import com.opencsv.bean.customconverter.ConvertSplitOnWhitespace; import java.util.Date; import java.util.List; public class User { @CsvBindByName(required = true) private Long id; @CsvBindByName(column = "User Name") private String name; private int age; @CsvBindByName @CsvDate("yyyy-MM-dd hh:mm:ss") private Date birthday; @CsvCustomBindByName(converter = ConvertSplitOnWhitespace.class) private Listtags; @CsvBindByName private boolean vip; public User(){ } public User(Long id, String name, int age, Date birthday, List tags, boolean vip) { this.id = id; this.name = name; this.age = age; this.birthday = birthday; this.tags = tags; this.vip = vip; } // Getter && Setter && toString() }
@Test public void testCSVWriteByAnnotation() throws Exception{ Listusers = new ArrayList (); users.add(new User(1L, "张'三'", 20, new Date(), Arrays.asList("eat", "drink", "girl"), true)); users.add(new User(2L, "李,四", 21, new Date(), Arrays.asList("mm", "money"), false)); users.add(new User(3L, "王\n五", 22, new Date(), Arrays.asList("girl", "$"), true)); OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream("D:\\test.csv"), Charset.forName("UTF-8")); StatefulBeanToCsv beanToCsv = new StatefulBeanToCsvBuilder(writer).withSeparator('\t').withQuotechar('\'').build(); beanToCsv.write(users); writer.close(); }
@Test public void testCSVReadByAnnotation() throws Exception{ InputStreamReader in = new InputStreamReader(new FileInputStream("D:\\test.csv"), Charset.forName("UTF-8")); HeaderColumnNameMappingStrategy strategy = new HeaderColumnNameMappingStrategy(); strategy.setType(User.class); CsvToBean csvToBean = new CsvToBeanBuilder(in).withSeparator('\t').withQuoteChar('\'').withMappingStrategy(strategy).build(); List users = csvToBean.parse(); for(User user: users) { System.out.println(user); } }