JAVA CSV内容生成(针对导出数据量大,excel不适合)
程序员文章站
2022-06-01 14:10:04
...
CSV内容生成(针对导出数据量大,excel不适合)
)
众所周知,csv文件编辑器打开,列之间以“,”逗号相隔
问:列字段值包含逗号应该怎么办?
答:字段用双引号包起来。
问:若该字段值也有双引号怎么办?
答:在双引号前添加一个双引号,字段整体再用双引号包起来。
举例
代码参考
public class CSVUtils {
private CSVUtils() {
}
/* 列分隔符 */
private static final String COLUMN_SEPARATOR = ",";
/* 行分隔符 */
private static final String ROW_SEPARATOR = "\r\n";
/* 字符:引号 */
private static final String MARK_QUAT = "\"";
public static <T> String createByBean(String[] header, List<T> data) {
return create(header, data.stream().filter(Objects::nonNull).map(row ->
ReflectUtils.getFields(row.getClass()).stream().filter(field -> !"serialVersionUID".equals(field.getName()))
.map(field -> {
try {
field.setAccessible(true);
return field.get(row);
} catch (Exception e) {
throw new RuntimeException(e);
}
}).collect(toList())
).collect(toList()));
}
public static String create(String[] header, List<List<Object>> data) {
StringBuffer buf = new StringBuffer();
AssertBiz.notEmpty(header, "header is Empty.");
buf.append(Arrays.stream(header).map(CSVUtils::convert).collect(joining(COLUMN_SEPARATOR)));
buf.append(ROW_SEPARATOR);
data.stream().filter(Objects::nonNull).forEach(row -> {
buf.append(row.stream().map(CSVUtils::convert).collect(joining(COLUMN_SEPARATOR)));
buf.append(ROW_SEPARATOR);
});
return buf.toString();
}
private static String convert(Object column) {
if (null == column) {
return "";
}
if (column instanceof String) {
return stringAlter(String.class.cast(column));
}
if (column instanceof Date) {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date.class.cast(column));
}
return column.toString();
}
private static String stringAlter(String column) {
if (null == column || StringUtils.isBlank(column)) {
return "";
}
if (column.contains(MARK_QUAT)) {
int[] indexs = indexOf(column, MARK_QUAT);
StringBuilder tmp = new StringBuilder(column);
IntStream.range(0, indexs.length).forEach(i -> tmp.insert(i + indexs[i], MARK_QUAT));
return MARK_QUAT + tmp.toString() + MARK_QUAT;
}
if (column.contains(COLUMN_SEPARATOR)) {
return MARK_QUAT + column + MARK_QUAT;
}
return column;
}
private static int[] indexOf(String source, String target) {
List<Integer> indexs = new ArrayList<>();
int tmp = source.indexOf(target);
while (tmp > -1) {
indexs.add(tmp);
tmp = source.indexOf(target, tmp + 1);
}
return indexs.stream().mapToInt(Integer::valueOf).toArray();
}
}