生成的对象不确定?自己封装出来函数支撑不同的类,自动去读取遍历list,然后导出生成csv文件。
1、简介
实现万能的工具类生成csv文件,当不确定类的集合list时,通过反射取出里面的属性名,做第一行表格行标题;通过反射吧类全部字段属性作为key放到map里,同时把值放到value里。
2、工具类
话不多说,直接上代码
public class CsvFileUtil {
public static final String FILE_SUFFIX = ".csv";
public static final String CSV_DELIMITER = ",";
public static final String CSV_TAIL = "\r\n";
protected static final String DATE_STR_FILE_NAME = "yyyyMMddHHmmssSSS";
/**
* 将字符串转成csv文件
*
* @param savePath
* @param contextStr
* @throws IOException
*/
public 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
*/
public 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) {
//log.error("写文件异常|{}", e);
} finally {
if (fos != null) {
IOUtils.closeQuietly(fos);
}
if (writer != null) {
IOUtils.closeQuietly(writer);
}
}
}
/**
* 构建文件名称
*
* @param dataList
* @return
*/
public 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
* @return
*/
public 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(CsvFileUtil.CSV_DELIMITER);
}
return tableNames.append(CsvFileUtil.CSV_TAIL).toString();
}
/**
* 构建excel内容
*
* @param dataLists
* @return
*/
public 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(CsvFileUtil.CSV_DELIMITER);
} else {
lineBuilder.append("--").append(CsvFileUtil.CSV_DELIMITER);
}
}
lineBuilder.append(CsvFileUtil.CSV_TAIL);
}
return lineBuilder.toString();
}
/**
* 类转map
*
* @param entity
* @param <T>
* @return
*/
public static <T> Map<String, Object> toMap(T entity) {
Class<? extends Object> bean = entity.getClass();
Field[] fields = bean.getDeclaredFields();
Map<String, Object> map = new HashMap<>(fields.length);
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) {
//log.warn("toMap() Exception={}",e.getMessage());
}
}
return map;
}
}
注意,toMap方法,通过反射取值。
3、测试
新建springboot工程,此处不再赘述。
测试接口如下;
@RequestMapping("/createCsvFile")
public void createCsvFile() {
//类不确定 随便怎么传都行
List<District> districts = new ArrayList<>();
District district = new District();
district.setCode("0001");
district.setName("caocao");
district.setParentCode("01");
district.setFullName("三国曹操");
districts.add(district);
District district2 = new District();
district2.setCode("0002");
district2.setName("sunquan");
district2.setParentCode("02");
district2.setFullName("三国孙权");
districts.add(district2);
District district3 = new District();
district3.setCode("0003");
district3.setName("liubei");
district3.setParentCode("03");
district3.setFullName("三国刘备");
districts.add(district3);
//存放地址&文件名
String fileName = "D:\\csv\\"+ CsvFileUtil.buildCsvFileFileName(districts);
//表格行标题
String tableNames = CsvFileUtil.buildCsvFileTableNames(districts);
//创建文件
CsvFileUtil.writeFile(fileName, tableNames);
//文件数据
String contentBody = CsvFileUtil.buildCsvFileBodyMap(districts);
//调用方法生成
CsvFileUtil.writeFile(fileName, contentBody);
}
模拟了3条数据,对象为Distinct对象,可以替换为其他对象,在指定的路径下(目录需存在)生成指定的csv文件,结果如下:
csv文件内容如下:
非常简单,小伙伴们快去试试吧~