目录
一、场景:
在对数据进行导出时,发现导出为Excel会导致服务器内存溢出,经排查,是因为导出为Excel时,每个单元格都会先存放到内存里,单元格太多导致内存溢出,所以改用为csv文件导出。
二、避坑指南:
1.csv文件的分隔符是可指定的,一般默认为英文逗号“,”,想要单元格样式的分隔符,需要引入common-csv jar包;
2.csv文件的编码格式要特别注意,否则导出来数据就是乱码。
三、简单版读写代码:
1、csv写入
/**
* 写入CSV,csv文件分隔符,默认“,”
*
* @param filePath csv文件路径
* @param list 数据集
* @param charsetName,默认GBK
* @return
*/
public static void writeCSV(String filePath, List<String> list,String charsetName) {
try {
if (ValidateUtils.isEmpty(charsetName)) {
charsetName = "GBK";
}
OutputStreamWriter outputStreamWriter =
new OutputStreamWriter(new FileOutputStream(filePath), charsetName);
BufferedWriter writer = new BufferedWriter(outputStreamWriter);
for (String s : list) {
writer.write(s);
writer.newLine();
}
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
2、读取
/**
* 读取
*
* @param path csv文件路径
* @param csvSplit csv文件分隔符,默认“,”
* @param charsetName csv文件编码格式,默认GBK
* @return
*/
public static List<Map<String, String>> readCsv(String path, String csvSplit, String charsetName) throws IOException {
List<Map<String, String>> results = new ArrayList<>();
BufferedReader bReader = null;
File file = new File(path);
if (ValidateUtils.isEmpty(charsetName)) {
charsetName = "GBK";
}
try {
bReader = new BufferedReader(new InputStreamReader(new FileInputStream(file), charsetName));
String line = "";
//忽略第一行标题
List<String> titles = new ArrayList<>();
String titleArr[] = bReader.readLine().split(csvSplit);
for (String title : titleArr) {
titles.add(title);
}
while ((line = bReader.readLine()) != null) {
if (line.trim() != "") {
//分割开来的即是对应的每个单元格,注意空的情况
String valueArr[] = line.split(csvSplit);
int valueLength = valueArr.length;
Map<String, String> result = new HashMap<>();
for (int i = 0; i < titles.size(); i++) {
String title = titles.get(i);
String value = "";
if (i < valueLength) {
value = valueArr[i];
} else
value = null;
result.put(title, value);
}
results.add(result);
}
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (bReader != null) {
bReader.close();
}
}
return results;
}
四、commons-csv版读写代码:
1.引入pom(使用1.9.0版本)
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.9.0</version>
</dependency>
2.API应用
2.1.写入
/**
* @Description: convert list<Map<>> to csv
* @Param: headerList,valueList,pathName
* @return:
*/
public static void writeCsv(List<String> headerList,List<Map<String,String>> valueList,String pathName) {
try {
OutputStreamWriter outputStreamWriter =
new OutputStreamWriter(new FileOutputStream(pathName), "GBK");
BufferedWriter writer = new BufferedWriter(outputStreamWriter);
CSVPrinter printer = new CSVPrinter(writer, CSVFormat.EXCEL);
printer.printRecord(headerList);
for(Map<String,String> map : valueList) {
List<String> values = new ArrayList<>();
for(String header : headerList)
values.add(map.get(header));
printer.printRecord(values);
}
printer.close();
writer.close();
outputStreamWriter.close();
}catch (Exception e){
e.printStackTrace();
}
}
2.2读取
/**
* 读取,csv文件编码格式,默认GBK,可自己修改,拒绝中文乱码
*
* @param path csv文件路径
*
* @return
*/
public static JSONObject readCsv(String fileName) {
JSONObject results = new JSONObject();
try {
File file = new File(fileName);
BufferedReader bReader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "GBK"));
CSVParser parser = CSVFormat.DEFAULT.parse(bReader);
//标题
List<String> titles = new ArrayList<>();
List<CSVRecord> records = parser.getRecords();
if (records!=null && records.size()>0){
CSVRecord titleRecord = records.get(0);
for (int i = 0; i < titleRecord.size(); i++) {
titles.add(titleRecord.get(i));
}
results.put("title",titles);
}
if (records.size()>1){
List<Map<String, String>> values = new ArrayList<>();
for (int i = 1; i < records.size(); i++) {
CSVRecord record = records.get(i);
Map<String, String> map = new HashMap<>();
for (int j = 0; j < record.size(); j++) {
String value = record.get(j);
String title = titles.get(j);
map.put(title,value);
}
values.add(map);
}
results.put("values",values);
}
parser.close();
bReader.close();
} catch (Exception e) {
e.printStackTrace();
}
return results;
}
五、结语
实际工作中,很多数据都存在csv文件中,使用 java语言开发的时候,有的时候需要读取文件,或者将csv文件导入到数据库中,commons-csv作为三方类库,简化了读取操作!
欢迎留言讨论!