@[toc]
一、案例描述
- 方法1:把list封装成CSV数据文件返回file对象
- 方法2:把list封装成CSV数据文件输出到指定文件目录
二、什么是CSV文件
三、注意点使用说明
注意点1:
CsvUtilBack是把list封装csv的工具
DateUtilBack是日期相关工具
ExportUtil是分页先关工具
注意点2:
File file = new File(pathname); 的形参pathname可以带路径path+fileName,也可以只带文件名fileName
注意点3:
封装的方法listToCsvFileSaveToDirectory中,注意往csv文件设置内容时,这里必须传string,不能传对象.toString(),否则存入的值就不对了,所以才有了先把 List转换成List的步骤,详情请看方法工具类CsvUtilBack封装的listToCsvFileSaveToDirectory方法。
四、完整代码
pom依赖
<!--导出成csv文件-->
<dependency>
<groupId>net.sf.supercsv</groupId>
<artifactId>super-csv</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>com.github.mygreen</groupId>
<artifactId>super-csv-annotation</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>4.2</version>
</dependency>
Controller
ListToCsvController
import com.example.demo.bean.Subscriber;
import com.example.demo.util.CsvUtilBack;
import com.example.demo.util.ExportUtil;
import java.util.ArrayList;
import java.util.List;
/**
* 测试使用把list封装成csv文件
* @Author 211145187
* @Date 2022/6/21 09:50
**/
public class ListToCsvController {
/**
* 模拟使用场景描述:假设list是从数据库查出的拥有至少10w条数据的集合信息,假设pageSize是我从配置文件读出的配置信息,通过for循环就可以把10W条数据按照pageSize分成10份文件上传到服务器上,模拟的是方案2实现方式
* 实现方案有2种:
* 第一种:每次分页查询1W条数据 =》 封装成file上传指定服务器
* 第二种:一次查询10W条数据 =》 通过for循环就可以把10W条数据按照pageSize分成10份文件上传到服务器上
*/
public static void main(String[] args) {
List<Subscriber> list = new ArrayList<>();
list.add(new Subscriber(1000500, 123456, "dy1", 1, 1, 0));
list.add(new Subscriber(1000501, 123456, "dy2", 1, 3, 0));
list.add(new Subscriber(1000502, 123456, "dy3", 1, 5, 0));
//假设pageSize是我从配置文件读出的配置信息
Integer pageSize = 10000;
Integer pageCount = ExportUtil.getPageCount(list.size(), pageSize);
String filePath = "D:\\laji-file";
String fileName = "userModelList";
for(Integer pageNum = 1; pageNum < pageCount + 1; pageNum++){
try {
List<Subscriber> pageList = ExportUtil.getPageList(list, pageNum, pageSize, pageCount);
List<String> fileStr = CsvUtilBack.ListToCsv(pageList);
//调用方法1:把list封装成CSV数据文件输出到指定文件目录
CsvUtilBack.listToCsvFileSaveToDirectory(fileStr, filePath, fileName);
System.out.println("--ListToCsvFileSaveToDirectory-upload-success");
//调用方法2:把list封装成CSV数据文件返回file对象
// File file = CsvUtilBack.returnListToCsvFile(fileStr, fileName);
// System.out.println("--returnListToCsvFile-upload-success" + file);
} catch (Exception e) {
e.printStackTrace();
break;
}
}
}
}
实体bean
Subscriber
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Subscriber implements Serializable {
//序列号
private int subscriberNumber;
//密码
private int Password;
//别名
private String subscriberAlias;
//是否允许修改密码【0:Deny、1:Allow】
private int changePassword;
//用户类型【1:SIP Terminal、3:Audio/Video Recording Server、5:DC、6:Dispatch、7:Mobile Radio】
private int subscriberType;
//状态【0:Normal、1:Stunned、2:Kiled】
private int status;
}
工具类
CsvUtilBack
package com.example.demo.util;
import com.github.mygreen.supercsv.annotation.CsvColumn;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class CsvUtilBack {
//日期:2020-07-24
//作者:150513701
//描述:List<T>转List<String>
public static <T> List<String> ListToCsv(List<T> list) {
if (list == null || list.isEmpty()) {
return new ArrayList();
}
boolean first = true;
List<String> resultList = new ArrayList<>();
for (T t : list) {
List<String> nameList = new ArrayList<>();
List<String> valueList = new ArrayList<>();
Field[] fields = t.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
field.setAccessible(true); //这句话的目的是为了能够通过反射读取JAVA类中Private修饰的变量
try {
Object fieldValue = field.get(t);
Object fieldType = field.getType();
if (fieldValue != null) {
if (first) {
//第一次进入函数需要获取列名
CsvColumn annotation = field.getAnnotation(CsvColumn.class);
if (annotation == null) {
nameList.add(field.getName());
} else {
nameList.add(annotation.label());
}
}
if (((Class) fieldType).getName() == "java.util.Date") {
Date date = (Date) fieldValue;
valueList.add(DateUtilBack.formatDate(date, "yyyy-MM-dd HH:mm:ss"));
} else {
valueList.add(fieldValue.toString());
}
}
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
}
//添加列头
if (first) {
resultList.add(String.join(",", nameList));
first = false;
}
//添加列值
resultList.add(String.join(",", valueList));
}
return resultList;
}
/**
* 描述:把list封装成CSV数据文件返回file对象
* 使用场景:方法返回csv文件,用于上传文件服务器或者上传windows路径下
* @param list 数据集合
* @param fileName 文件名称
* @return File
*/
public static File returnListToCsvFile(List<String> list, String fileName) {
File csvFile = null;
BufferedWriter csvWriter = null;
try {
csvFile = new File(fileName);
File parent = csvFile.getParentFile();
if (parent != null && !parent.exists()) {
parent.mkdirs();
}
//创建文件
csvFile.createNewFile();
csvWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(csvFile), "UTF-8"), 1024);
//写入内容
for (String str : list) {
csvWriter.write(str);
csvWriter.newLine();
}
csvWriter.flush();
} catch (Exception e) {
e.printStackTrace();
}
finally {
try {
csvWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return csvFile;
}
/**
* 描述:把list封装成CSV数据文件输出到指定文件目录
* 使用场景:直接将csv文件上传到指定目录下
* @param list 数据集合
* @param fileName 文件名称
* @param filePath 保存路径
*/
public static void listToCsvFileSaveToDirectory(List<String> list, String filePath, String fileName) {
File csvFile = null;
BufferedWriter csvWriter = null;
try {
//创建文件
csvFile = new File(filePath + File.separator + fileName + ".csv");
File parent = csvFile.getParentFile();
if (parent != null && !parent.exists()) {
parent.mkdirs();
}
csvFile.createNewFile();
csvWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(csvFile), "UTF-8"), 1024);
//写入内容
for (String str : list) {
csvWriter.write(str); //注意点1:这里必须传string,不能传对象.toString(),否则存入的值就不对了,所以才有了先把 List<Subscriber>转换成List<String>的步骤
csvWriter.newLine();
}
csvWriter.flush();
} catch (Exception e) {
e.printStackTrace();
}
finally {
try {
csvWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
DateUtilBack
package com.example.demo.util;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateUtilBack {
/**
* 格式化日期
*
* @param date 日期
* @param format 日期格式
* @return
*/
public static String formatDate(Date date, String format) {
if (format == null || format.equals("")) {
format = "yyyy-mm-dd";
}
if (date == null) {
return "";
} else {
SimpleDateFormat df = new SimpleDateFormat(format);
return df.format(date);
}
}
}
ExportUtil
package com.example.demo.util;
import java.util.List;
public class ExportUtil {
/***
* 自定义获取分页总页数的方法
* 传参:list总数、页容量
* 返回:总页数
*/
public static Integer getPageCount(Integer count, Integer pageSize){
Integer pageCount = 0;
if(count.equals(0)){
return pageCount;
}
pageCount = count/pageSize;
if(count % pageSize != 0){
pageCount++;
}
return pageCount;
}
/**
* 自定义List分页工具
* 传参:待分页的list数据、页码、页容量
* 返回值:分页后的list数据
*/
public static <T> List<T> getPageList(List<T> list, Integer pageNum, Integer pageSize, Integer pageCount){
/**开始索引*/
int beginIndex = 0;
/**结束索引*/
int endIndex = 0;
Integer compare = pageNum.compareTo(pageCount);
if(!compare.equals(0)){
beginIndex = (pageNum - 1) * pageSize;
endIndex = beginIndex + pageSize;
}else{
beginIndex = (pageNum - 1) * pageSize;
endIndex = list.size();
}
List pageList = list.subList(beginIndex, endIndex);
return pageList;
}
}
五、注意点3中错误代码和正确代码的不同结果展示
错误代码
public static void listToCsvFileSaveToDirectory(List<Subscriber> list, String filePath, String fileName) {
...
for (Subscriberstr : list) {
csvWriter.write(str.toString());
csvWriter.newLine();
}
...
错误结果展示
正确代码
public static void listToCsvFileSaveToDirectory(List<String> list, String filePath, String fileName) {
...
for (String str : list) {
csvWriter.write(str);
csvWriter.newLine();
}
...