一、csv
1、介绍
CSV(Comma-Separated Values,逗号分隔的值)是一种简单、实用的文件格式,用于存储和表示包括文本、数值等各种类型的数据。CSV 文件通常以 .csv 作为文件扩展名。这种文件格式的一个显著特点是:文件内的数据以逗号 , 分隔,呈现一个表格形式。CSV 文件已广泛应用于存储、传输和编辑数据。
2、结构
(1)每行表示一条记录:CSV 文件中的每一行代表一条记录,相当于数据库中的一行数据。第一行是字段名。
(2)间隔符分隔:每行数据中,使用间隔符进行数据分隔,默认一般使用 , ,也可以使用空格等其他字符,代表不同的数据。经过测试,好像只有逗号分隔的csv文件才能在Excel中正常解析。
(3)引号包围:当数据单元格中的内容含有逗号时,为避免混淆,需要引号 (单引号 ' 或双引号 ")将这个数据包围起来,防止误认为是两个不同数据。
如
姓名,年龄,性别
张三,25,男
李四,28,男
王五,22,女
3、优点
简单易懂:CSV 文件基于纯文本格式,因此可以使用任何文本编辑器(如Notepad++)轻松打开和编辑。
数据兼容性:CSV 文件中的数据可以很容易地跨平台进行传输和处理,任何具有 CSV 处理功能的软件(如Microsoft Excel、Google Sheets、甚至编程语言库)都能处理该类型的文件。
资源占用低:CSV 文件以纯文本形式存储数据,其体积相对较小,便于节省存储空间。
4、csv和excel的区别
1.CSV是纯文本文件,excel不是纯文本,Excel是一个二进制文件,它保存有关工作簿中所有工作表的信息。
2.CSV文件的体积会更小,创建分发读取更加方便,适合存放结构化信息,比如记录的导出,流量统计等等。
3.CSV文件在windows平台默认的打开方式是excel,但是它的本质是一个文本文件。
4、一个csv只能有一个sheet;一个excel可以有多个sheet。
5、由于数值和文本之间没有明确的区别或区分,Excel可以使用自动格式化功能搞乱您的邮政编码和信用卡号码
CSV是安全的,可以清楚地区分数值和文本。CSV不处理数据并按原样存储。
6、Excel导入数据时消耗更多的内存
导入CSV文件可以更快,而且消耗更少的内存
7、Excel文件只能用Microsoft Excel文档打开
CSV可以用Windows中的任何文本编辑器打开,如记事本,MS Excel,Microsoft Works 9等
二、写入数据到csv
openCSV是最简单易懂的CSV解析器之一,它使用标准Reader/Writer类并CSVReader在顶部提供实现。OpenCSV读取CSV的速度比使用Apache Commons CSV读取的速度要快,因为CSVWriter使用该CSVToBean.parse()方法时,将CSV实现为多线程的。
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>4.0</version>
</dependency>
/**
* 导出
* @param outFileName
* @param users
* @throws Exception
*/
public static void writerFile(String outFileName, List<UserDTO> users) throws Exception {
FileWriter fileWriter = new FileWriter(outFileName);
CSVWriter csvWriter = new CSVWriter(fileWriter,
CSVWriter.DEFAULT_SEPARATOR,
CSVWriter.NO_QUOTE_CHARACTER,
CSVWriter.DEFAULT_ESCAPE_CHARACTER,
CSVWriter.DEFAULT_LINE_END);
String[] header = { "name", "age", "email"};
csvWriter.writeNext(header);
String[] row = new String[header.length];
for (UserDTO userDTO : users) {
row[0] = userDTO.getUserName();
row[1] = String.valueOf(userDTO.getAge());
row[2] = userDTO.getEmail();
csvWriter.writeNext(row, true);
csvWriter.flush();
}
csvWriter.close();
}
测试:
@Test
public void exportCSV() throws Exception {
UserDTO user1 = UserDTO.builder()
.userName("张三")
.age(18)
.email("zhangsan@test.com")
.build();
UserDTO user2 = UserDTO.builder()
.userName("李四")
.age(20)
.email("lisi@test.com")
.build();
List<UserDTO> users = Arrays.asList(user1, user2);
String fileName = "/test/user.csv";
CSVUtil.writerFile(fileName,users);
}
查看生成的文件:
使用idea打开查看内容:
三、解析csv文件
手动解析或者使用工具解析:
1、手动解析
// 析csv文件并转成bean(方法一)
public static List<CsvFile> getCsvDataMethod1(MultipartFile file) {
ArrayList<CsvFile> csvFileList = new ArrayList<>();
InputStreamReader in = null;
String s = null;
try {
in = new InputStreamReader(file.getInputStream(), "utf-8");
BufferedReader bufferedReader = new BufferedReader(in);
String line = null;
while ((line = bufferedReader.readLine()) != null) {
String[] split = line.split(",");
CsvFile csvFile = new CsvFile();
csvFile.setName(splitResult(split[0]));
csvFile.setTitle(splitResult(split[1]));
csvFile.setNumber(splitResult(split[2]));
csvFile.setType(splitResult(split[3]));
csvFile.setPersonnel(splitResult(split[4]));
csvFile.setTime(splitResult(split[5]));
csvFileList.add(csvFile);
}
} catch (IOException e) {
e.printStackTrace();
}
return csvFileList;
}
//去重引号""
private static String splitResult(String once) {
String result = "";
for (int i = 0; i < once.length(); i++) {
if (once.charAt(i) != '"') {
result += once.charAt(i);
}
}
return result;
}
2、openCSV解析CSV文件
解析成数组:
/**
* 解析csv文件并转成bean(方法二)
*
* @param file csv文件
* @return 数组
*/
public static List<String[]> getCsvDataMethod2(MultipartFile file) {
List<String[]> list = new ArrayList<String[]>();
int i = 0;
try {
CSVReader csvReader = new CSVReaderBuilder(
new BufferedReader(
new InputStreamReader(file.getInputStream(), "utf-8"))).build();
Iterator<String[]> iterator = csvReader.iterator();
while (iterator.hasNext()) {
String[] next = iterator.next();
//去除第一行的表头,从第二行开始
if (i >= 1) {
list.add(next);
}
i++;
}
return list;
} catch (Exception e) {
System.out.println("CSV文件读取异常");
return list;
}
}
解析成对象:
/**
* 解析csv文件并转成bean(方法三)
*
* @param file csv文件
* @param clazz 类
* @param <T> 泛型
* @return 泛型bean集合
*/
public static <T> List<T> getCsvDataMethod3(MultipartFile file, Class<T> clazz) {
InputStreamReader in = null;
CsvToBean<T> csvToBean = null;
try {
in = new InputStreamReader(file.getInputStream(), "utf-8");
HeaderColumnNameMappingStrategy<T> strategy = new HeaderColumnNameMappingStrategy<>();
strategy.setType(clazz);
csvToBean = new CsvToBeanBuilder<T>(in).withMappingStrategy(strategy).build();
} catch (Exception e) {
logger.error("数据转化失败");
return null;
}
return csvToBean.parse();
}