Skip to content

Commit

Permalink
feat: 增加工具类:导入导出CSV文件的两种实现方式。
Browse files Browse the repository at this point in the history
1) 直接使用IO读取csv文件的每一行数据;
2) 使用第三方jar包导入导出csv文件;
  • Loading branch information
GitSuperDrew committed Feb 23, 2021
1 parent 2eaef66 commit 9e95794
Show file tree
Hide file tree
Showing 3 changed files with 339 additions and 0 deletions.
11 changes: 11 additions & 0 deletions springboot-aop/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,17 @@
<artifactId>spring-kafka-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
</dependency>
<!--第三方jar包,操作csv文件的导入导出-->
<dependency>
<groupId>net.sourceforge.javacsv</groupId>
<artifactId>javacsv</artifactId>
<version>2.0</version>
</dependency>
</dependencies>

<build>
Expand Down
237 changes: 237 additions & 0 deletions springboot-aop/src/main/java/com/study/module/util/office/CsvUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
package com.study.module.util.office;

import com.alibaba.fastjson.JSONObject;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.util.ObjectUtils;

import java.io.*;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

/**
* CSV 转换程 excel
*
* @author drew
* @date 2021/2/23 10:32
**/
public class CsvUtil {

private static CsvUtil instance;

public CsvUtil() {
}

public static CsvUtil getInstance() {
if (instance == null) {
synchronized (CsvUtil.class) {
if (instance == null) {
instance = new CsvUtil();
}
}
}
return instance;
}

public static void main(String[] args) throws Exception {

testReadCsv();
// testExportCsv();
// testExportCsvPlus();
}

private static void testReadCsv() {
while (true) {
System.out.println("读取csv文件的数据:(示例文件地址为:D:/csv-demo-1.csv)");
Scanner scanner = new Scanner(System.in);
String in = scanner.nextLine();
if ("exit".equals(in)) {
break;
}
System.out.println("文件的数据如下:\n" + JSONObject.toJSONString(readCsv(in)));
}
}

private static void testExportCsv() {
String birthDay = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
List<Object> head = Arrays.asList("姓名", "年龄", "成绩", "性别", "出生日期", "是否有效");
List<List<Object>> dataList = Arrays.asList(
Arrays.asList("Drew", 23, 99.4, birthDay, "男", true),
Arrays.asList("Mark", 43, 43.5, null, "男", true),
Arrays.asList("Bob", 20, 20.0, "", "男", true),
Arrays.asList("King", 19, null, null, "男", true),
Arrays.asList("King", null, null, null, "男", true)
);
String outPutPath = "D:/";
String filename = UUID.randomUUID().toString().substring(0, 8);

exportCsv(head, dataList, outPutPath, filename);
System.out.println("生成 CSV 文件成功!文件位置为:" + outPutPath + filename);
}

public static void testExportCsvPlus() throws IOException, IllegalArgumentException, IllegalAccessException {
String[] titles = new String[]{"姓名", "年龄", "成绩", "性别", "出生日期", "是否有效"};
String[] propertys = new String[]{"name", "age", "grades", "sex", "birthday", "enabled"};
User user = new User();
user.setName("abc");
user.setAge(null);
user.setGrades(45.5F);
user.setSex("");
user.setBirthday(new Date());
user.setEnabled(true);

List<User> dataList = Arrays.asList(user, user, user);
String outputFilePath = "D:/" + UUID.randomUUID().toString().replaceAll("-", "").concat(".csv");
CsvUtil.exportCsvPlus(titles, propertys, dataList, outputFilePath);
System.out.println("导出成功,位置为:" + outputFilePath);
}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
static class User {
private String name;
private Integer age;
private Float grades;
private String sex;
private Date birthday;
private Boolean enabled;
}


/**
* 读取csv文件的数据
*
* @param csvFilePath csv文件所在位置(例如:“D:\评价数据.csv”)
* @return 数据集合
*/
public static List<List<Object>> readCsv(String csvFilePath) {
List<List<Object>> result = new ArrayList<>();
try {
//换成你的文件名
BufferedReader reader = new BufferedReader(new FileReader(csvFilePath));
reader.readLine();//第一行信息,为标题信息,不用,如果需要,注释掉
String line = null;
while ((line = reader.readLine()) != null) {
//CSV格式文件为逗号分隔符文件,这里根据逗号切分
List<Object> item = Arrays.asList(line.split(","));
if (!ObjectUtils.isEmpty(item)) {
// TODO 针对item集合中的每一个数据,可以进行具体类型转换(例如转称 integer类型,string类型,集合set/list类型等)
result.add(item);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return result;
}

/**
* 导出生成csv格式的文件
*
* @param titles csv格式头文
* @param properties 需要导出的数据实体的属性,注意与title一一对应
* @param list 需要导出的对象集合
* @param outPutFilePath 输出文件地址(例如:D:\\test.csv)
* @return
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
public static <T> String exportCsvPlus(String[] titles, String[] properties, List<T> list, String outPutFilePath) throws IOException, IllegalArgumentException, IllegalAccessException {
File file = new File(outPutFilePath);
//构建输出流,同时指定编码
OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream(file), "gbk");

//csv文件是逗号分隔,除第一个外,每次写入一个单元格数据后需要输入逗号
for (String title : titles) {
ow.write(title);
ow.write(",");
}
//写完文件头后换行
ow.write("\r\n");
//写内容
for (Object obj : list) {
//利用反射获取所有字段
Field[] fields = obj.getClass().getDeclaredFields();
for (String property : properties) {
for (Field field : fields) {
//设置字段可见性
field.setAccessible(true);
if (property.equals(field.getName())) {
ow.write(String.valueOf(field.get(obj)));
ow.write(",");
}
}
}
//写完一行换行
ow.write("\r\n");
}
ow.flush();
ow.close();
return "0";
}


/**
* CSV文件生成方法
*
* @param head 表头信息
* @param dataList 具体数据信息
* @param outPutPath 数据文件路径(例如:”D:/outCsvDir/“)
* @param filename 自定义文件名(例如:”csv-out-file“)
* @return
*/
public static File exportCsv(List<Object> head, List<List<Object>> dataList, String outPutPath, String filename) {
File csvFile = null;
BufferedWriter csvWriter = null;
try {
csvFile = new File(outPutPath + File.separator + filename + ".csv");
File parent = csvFile.getParentFile();
if (parent != null && !parent.exists()) {
parent.mkdirs();
}
csvFile.createNewFile();

// GB2312使正确读取分隔符","
csvWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(csvFile), "GB2312"), 1024);
// 写入文件头部
writeRow(head, csvWriter);

// 写入文件内容
for (List<Object> row : dataList) {
writeRow(row, csvWriter);
}
csvWriter.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
csvWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return csvFile;
}

/**
* 写一行数据方法
*
* @param row
* @param csvWriter
* @throws IOException
*/
private static void writeRow(List<Object> row, BufferedWriter csvWriter) throws IOException {
// 写入文件头部
for (Object data : row) {
String rowStr = "\"" + data + "\",";
csvWriter.write(rowStr);
}
csvWriter.newLine();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package com.study.module.util.office;

import com.alibaba.fastjson.JSONObject;
import com.csvreader.CsvReader;
import com.csvreader.CsvWriter;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;

/**
* 引入第三方的jar包操作CSV文件(导入导出)
*
* @author drew
* @date 2021/2/23 13:45
**/
public class CsvUtilPlus {

public static void main(String[] args) throws Exception {
// 生成CSV文件
String outputFilePath = "D:/" + UUID.randomUUID().toString().substring(0, 4) + ".csv";
List<String> headers = Arrays.asList("姓名", "年龄", "性别", "成绩");
List<List<String>> content = Arrays.asList(
Arrays.asList("drew", "12", "男", null),
Arrays.asList(),
Arrays.asList(),
Arrays.asList("Mark", "", null, "89.3"),
Arrays.asList()
);
writer(headers, content, outputFilePath);
System.out.println("导出CSV文件成功, 文件所在位置:" + outputFilePath);

// 读取上方生成的CSV文件
System.out.println("读取数据成功,数据如下:\n" + JSONObject.toJSONString(read(outputFilePath)));
}

/**
* 读取 CSV 文件的数据【读物CSV文件的API:http://javacsv.sourceforge.net/com/csvreader/CsvReader.html】
*
* @param srcCsvPath csv文件存放的位置(例如:"F:/demo.csv")
* @throws IOException
*/
public static List<List<String>> read(String srcCsvPath) throws IOException {
List<List<String>> result = new LinkedList<>();
// 第一参数:读取文件的路径 第二个参数:分隔符(不懂仔细查看引用百度百科的那段话) 第三个参数:字符集
CsvReader csvReader = new CsvReader(srcCsvPath, ',', StandardCharsets.UTF_8);

// 如果你的文件没有表头,这行不用执行;这行不要是为了从表头的下一行读,也就是过滤表头
csvReader.readHeaders();

// 读取每行的内容
while (csvReader.readRecord()) {
String lineData = csvReader.getRawRecord();
String[] arr = lineData.split(",");
result.add(Arrays.asList(arr));

// // 获取内容的两种方式
// // 1. 通过下标获取
// System.out.print(csvReader.get(0));
// // 2. 通过表头的文字获取
// System.out.println(" " + csvReader.get("年龄"));
}
return result;
}


/**
* 导出CSV文件(写入CSV文件的API:http://javacsv.sourceforge.net/com/csvreader/CsvWriter.html)
*
* @param outPutFilePath csv文件输出路径(例如:"D:/demo.csv")
* @param headers 表头
* @param content 数据集合
* @throws IOException
*/
public static void writer(List<String> headers, List<List<String>> content, String outPutFilePath) throws IOException {

// 第一参数:新生成文件的路径 第二个参数:分隔符(不懂仔细查看引用百度百科的那段话) 第三个参数:字符集
CsvWriter csvWriter = new CsvWriter(outPutFilePath, ',', StandardCharsets.UTF_8);
// 写表头和内容,因为csv文件中区分没有那么明确,所以都使用同一函数,写成功就行
csvWriter.writeRecord(headers.toArray(new String[0]));
for (List<String> line : content) {
csvWriter.writeRecord(line.toArray(new String[0]));
}
// 关闭csvWriter
csvWriter.close();
}

}

0 comments on commit 9e95794

Please sign in to comment.