java-tocsv
1、依赖
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.69</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.12</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
2、注解类
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyExcelName {
String value() default "";
}
3、实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class District implements Serializable {
/**
* 地址编码
*/
@MyExcelName("编码")
private String code;
/**
* 地址名称
*/
@MyExcelName("名称")
private String name;
/**
* 地址父级编码
*/
@MyExcelName("父级编码")
private String parentCode;
/**
* 当前地区对应的全称
*/
@MyExcelName("全称")
private String fullName;
}
4、工具类
/**
* <p>描述 : csv帮助类
*
* <p>路径 : cn.tjhis.utils
*
* <p>工程 : ExcelExport
*
* <p>作者 : wanghx
*
* <p>日期 : 2023-03-04 05:56
*
* @author : Administrator
*/
public class MyCsvFileUtil {
/**
* 文件后缀
*/
private static final String FILE_SUFFIX = ".csv";
/**
* 分隔符
*/
private static final String CSV_DELIMITER = ",";
/**
* 换行符
*/
private static final String CSV_TAIL = "\r\n";
/**
* 文件名称
*/
protected static final String DATE_STR_FILE_NAME = "yyyyMMddHHmmssSSS";
/**
* 将字符串转成csv文件
*/
private static void createCsvFile(String savePath, String contextStr) throws IOException {
File file = new File(savePath);
//创建文件
file.createNewFile();
//创建文件输出流
FileOutputStream fileOutputStream = new FileOutputStream(file);
//将指定字节写入此文件输出流
fileOutputStream.write(contextStr.getBytes("gbk"));
fileOutputStream.flush();
fileOutputStream.close();
}
/**
* 写文件
*
* @param fileName 文件名称
* @param content 内容
*/
private static void writeFile(String fileName, String content) {
FileOutputStream fos = null;
OutputStreamWriter writer = null;
try {
fos = new FileOutputStream(fileName, true);
writer = new OutputStreamWriter(fos, "GBK");
writer.write(content);
writer.flush();
} catch (Exception e) {
StaticLog.error("写文件异常|{}", e);
} finally {
if (fos != null) {
//关闭流
IOUtils.closeQuietly(fos);
}
if (writer != null) {
IOUtils.closeQuietly(writer);
}
}
}
/**
* 构建文件名称
*
* @param dataList list 数据
* @return 文件名称
*/
private static String buildCsvFileFileName(List dataList) {
return dataList.get(0).getClass().getSimpleName() + new SimpleDateFormat(DATE_STR_FILE_NAME).format(new Date()) + FILE_SUFFIX;
}
/**
* 构建excel 标题行名
*
* @param dataList list 数据
* @return 标题
*/
private static String buildCsvFileTableNames(List dataList) {
Map<String, Object> map = toMap(dataList.get(0));
StringBuilder tableNames = new StringBuilder();
for (String key : map.keySet()) {
tableNames.append(key).append(MyCsvFileUtil.CSV_DELIMITER);
}
return tableNames.append(MyCsvFileUtil.CSV_TAIL).toString();
}
/**
* 构建excel 标题行名
*
* @param dataList list 数据
* @return 标题
*/
private static String buildCsvFileTableNamesNew(List<String> dataList) {
StringBuilder tableNames = new StringBuilder();
for (String name : dataList) {
tableNames.append(name).append(MyCsvFileUtil.CSV_DELIMITER);
}
return tableNames.append(MyCsvFileUtil.CSV_TAIL).toString();
}
/**
* 构建excel内容
*
* @param dataLists list 数据
* @return 内容
*/
private static String buildCsvFileBodyMap(List dataLists) {
// 不管你传什么玩意,都搞成Map
List<Map<String, Object>> mapList = new ArrayList<>();
for (Object o : dataLists) {
mapList.add(toMap(o));
}
// 然后利用csv格式,对着map拼接数据
StringBuilder lineBuilder = new StringBuilder();
for (Map<String, Object> rowData : mapList) {
for (String key : rowData.keySet()) {
Object value = rowData.get(key);
if (Objects.nonNull(value)) {
lineBuilder.append(value).append(MyCsvFileUtil.CSV_DELIMITER);
} else {
lineBuilder.append("--").append(MyCsvFileUtil.CSV_DELIMITER);
}
}
lineBuilder.append(MyCsvFileUtil.CSV_TAIL);
}
return lineBuilder.toString();
}
/**
* 类转map
*
* @param entity 实体
* @param <T> 泛型
* @return 返回的map集合
*/
private static <T> Map<String, Object> toMap(T entity) {
Class<?> bean = entity.getClass();
Field[] fields = bean.getDeclaredFields();
Map<String, Object> map = new TreeMap<>();
for (Field field : fields) {
try {
if (!"serialVersionUID".equals(field.getName())) {
String methodName = "get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);
Method method = bean.getDeclaredMethod(methodName);
Object fieldValue = method.invoke(entity);
map.put(field.getName(), fieldValue);
}
} catch (Exception e) {
StaticLog.warn("toMap() Exception={}", e.getMessage());
}
}
return map;
}
/**
* 创建表格行标题 如果有注解 MyExcelName ,则用
*
* @param entity 实体
* @param <T> 实体
* @return 表头
*/
private static <T> List<String> resolveExcelTableName(T entity) {
Class<?> bean = entity.getClass();
Field[] fields = bean.getDeclaredFields();
Map<String, String> map = new TreeMap<>();
for (Field field : fields) {
try {
if (!"serialVersionUID".equals(field.getName())) {
String tableTitleName = field.getName();
MyExcelName myFieldAnn = field.getAnnotation(MyExcelName.class);
String annName = myFieldAnn.name();
// if (StrUtil.isNotBlank(annName)) {
// tableTitleName = annName;
// }
map.put(tableTitleName,annName);
}
} catch (Exception e) {
StaticLog.warn("toMap() Exception={}", e.getMessage());
}
}
return map.values().stream().toList();
}
/**
* 将文件导出到csv
*
* @param list 数据
* @param path 父级路径
* @param isShowChinese 表头是否显示中文
*/
public static String export(List list, String path, boolean isShowChinese) {
//存放地址&文件名
String fileName = path + buildCsvFileFileName(list);
String tableNames = "";
if (isShowChinese) {
// 创建表格行标题 注解名 ,可以是中文
tableNames = buildCsvFileTableNamesNew(resolveExcelTableName(list.get(0)));
} else {
// 创建表格行标题 属性名
tableNames = MyCsvFileUtil.buildCsvFileTableNames(list);
}
//创建文件
writeFile(fileName, tableNames);
//写入数据
String contentBody = buildCsvFileBodyMap(list);
//调用方法生成
writeFile(fileName, contentBody);
return fileName;
}
}
5、测试类
public class Main {
public static void main(String[] args) {
District district1 = new District("110101", "东城区", "110100", "北京北京市东城区");
District district2 = new District("110102", "西城区", "110100", "北京北京市西城区");
District district3 = new District("110105", "朝阳区", "110100", "北京北京市朝阳区");
District district4 = new District("110107", "石景山区", "110100", "北京北京市石景山区");
District district5 = new District("110108", "海淀区", "110100", "北京北京市海淀区");
District district6 = new District("110109", "门头沟区", "110100", "北京北京市门头沟区");
District district7 = new District("110111", "房山区", "110100", "北京北京市房山区");
District district8 = new District("110112", "通州区", "110100", "北京北京市通州区");
District district9 = new District("110113", "顺义区", "110100", "北京北京市顺义区");
District district10 = new District("110114", "昌平区", "110100", "北京北京市昌平区");
District district11 = new District("110115", "大兴区", "110100", "北京北京市大兴区");
District district12 = new District("110116", "怀柔区", "110100", "北京北京市怀柔区");
District district13 = new District("110117", "平谷区", "110100", "北京北京市平谷区");
District district14 = new District("110228", "密云区", "110100", "北京北京市密云区");
// 类不确定 随便怎么传都行
List<District> districts = new ArrayList<>();
districts.add(district1);
districts.add(district2);
districts.add(district3);
districts.add(district4);
districts.add(district5);
districts.add(district6);
districts.add(district7);
districts.add(district8);
districts.add(district9);
districts.add(district10);
districts.add(district11);
districts.add(district12);
districts.add(district13);
districts.add(district14);
String fileName = MyCsvFileUtil.export(districts, "d:\\",false);
MyCsvFileUtil.export(districts, "d:\\",true);
StaticLog.info("文件导出成功,文件名:{}", fileName);
}
}
6、效果图
- 原始表头
- 中文表头
世界上没有什么事情是跑步解决不了的,如果有,那就再跑一会!