笔者之前使用esayexcel的时候碰到了一个问题,就是easyexcel无法读取csv文件,所以迫不得已之下自己手写了一个统一读取的工具类,在这里分享一下,当然还有许多的不足之处,希望各位看官老爷们不吝指点
一、功能与局限
功能:
1、该工具类可以自动识别表格标题(默认每列的第一行为标题);
2、该工具累可以将读出的表格数据自动转化为实体类集合(表格标题必须要与实体类的属性名一致);
局限:
csv格式的文件只能读取第一页sheet中的表格,xls、xlsx文件是读取的选中sheet页的表格(也就是打开文件开到的那一页);
…
二、具体实现代码
1、需要的依赖
<!--读取xlsx、xls文件的包-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<!--读取csv文件的包-->
<dependency>
<groupId>net.sf.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>2.3</version>
</dependency>
<!--实体类转换需要的包-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68.noneautotype</version>
</dependency>
2、实现代码
工具类:
package com.muyichen.demo.util;
import au.com.bytecode.opencsv.CSVReader;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.muyichen.demo.vo.WorkBookTitleVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
@Slf4j
public class ExcelUtil<T> {
public static final String CSV_SUFFIX = ".csv";
public static final String XLS_SUFFIX = ".xls";
public static final String XLSX_SUFFIX = ".xlsx";
/**
* 转换特定类型的集合
* @param file
* @param requestId
* @param t
* @return
*/
@SuppressWarnings("unchecked")
public List<T> excelRead(MultipartFile file, String requestId, T t) {
List<JSONObject> jsonObjects = transExcelForMultipartFile(file, requestId);
String objs = JSON.toJSONString(jsonObjects);
return (List<T>) JSONObject.parseArray(objs, t.getClass());
}
/**
* 转换特定类型的集合
* @param file
* @param requestId
* @param c
* @return
*/
@SuppressWarnings("unchecked")
public List<T> excelReadForFile(File file, String requestId, Class<?> c) {
List<JSONObject> jsonObjects = transExcelForFile(file, requestId);
String objs = JSON.toJSONString(jsonObjects);
return (List<T>) JSONObject.parseArray(objs, c);
}
/**
* 读取上传Excel文件
* @param file
* @param requestId
* @return
*/
private static List<JSONObject> transExcelForMultipartFile(MultipartFile file, String requestId) {
List<JSONObject> resultList = null;
// 获取文件名
String fileName = file.getOriginalFilename();
// 获取文件后缀名,截取.后面的类容
assert fileName != null;
String suffix = fileName.substring(fileName.lastIndexOf("."));
try (InputStream inputStream = file.getInputStream()) {
resultList = transExcel(requestId, inputStream, suffix);
} catch (IOException e) {
log.error("【黑名单导入】导入文件解析异常,requestId:{},message:{}", requestId, e.getMessage());
e.printStackTrace();
}
return resultList;
}
/**
* 读取Excel文件
* @param file
* @param requestId
* @return
*/
private static List<JSONObject> transExcelForFile(File file, String requestId) {
List<JSONObject> resultList = null;
// 获取文件名
String fileName = file.getName();
// 获取文件后缀名,截取.后面的类容
String suffix = fileName.substring(fileName.lastIndexOf("."));
try (InputStream inputStream = new FileInputStream(file)) {
resultList = transExcel(requestId, inputStream, suffix);
} catch (IOException e) {
log.error("【黑名单导入】导入文件解析异常,requestId:{},message:{}", requestId, e.getMessage());
}
return resultList;
}
/**
* 根据文件后缀名区分读取Excel表格方法
* @param requestId
* @param inputStream
* @param suffix
* @return
*/
private static List<JSONObject> transExcel(String requestId, InputStream inputStream, String suffix) {
List<JSONObject> resultList = null;
if (XLS_SUFFIX.equals(suffix)) {
// .xls文件
resultList = readXlsFile(requestId, inputStream);
} else if (XLSX_SUFFIX.equals(suffix)) {
// .xlsx文件
resultList = readXlsxFile(requestId, inputStream);
} else if (CSV_SUFFIX.equals(suffix)) {
// .csv文件
resultList = readCsvFile(requestId, inputStream);
} else {
// 不支持格式,抛出异常
}
return resultList;
}
/**
* 读取xls文件
* @param requestId
* @param in
* @return
*/
private static List<JSONObject> readXlsFile(String requestId, InputStream in) {
List<JSONObject> resultList = new ArrayList<>();
HSSFWorkbook hssfWorkbook;
try {
hssfWorkbook = new HSSFWorkbook(in);
// 获取Excel中所有的sheet
// int sheetNum = hssfWorkbook.getNumberOfSheets();
// 获取导入之前Excel文档中的选中页
int activeSheetIndex = hssfWorkbook.getActiveSheetIndex();
// 获取选中页中的表格数据
HSSFSheet hssfSheet = hssfWorkbook.getSheetAt(activeSheetIndex);
//获取该页有多少行数据
int rowNum = hssfSheet.getLastRowNum();
//处理列名数据、自动转化表格标题名为列名
List<WorkBookTitleVO> workBookTitleVOS = analysisWorkBookForXls(hssfSheet);
for(int i = 1; i <= rowNum; i++) {
// 获取第i行数据
HSSFRow hssfRow = hssfSheet.getRow(i);
JSONObject obj = new JSONObject();
workBookTitleVOS.forEach(vo -> {
// 将所有字段都默认以字符串的格式读取
hssfRow.getCell(vo.getCellIndex()).setCellType(CellType.STRING);
obj.put(vo.getColumnName(), hssfRow.getCell(vo.getCellIndex()).toString());
});
resultList.add(obj);
}
} catch (IOException e) {
log.error("Xls文件解析异常,requestId:{},message:{}", requestId, e.getMessage());
}
return resultList;
}
/**
* 读取xlsx文件
* @param requestId
* @param in
* @return
*/
private static List<JSONObject> readXlsxFile(String requestId, InputStream in) {
List<JSONObject> resultList = new ArrayList<>();
XSSFWorkbook xssfWorkbook = null;
try {
//将InputStream转XLSX对象(即表格对象)
xssfWorkbook = new XSSFWorkbook(in);
// 获取导入之前Excel文档中的选中页
int activeSheetIndex = xssfWorkbook.getActiveSheetIndex();
// 获取选中页中的表格数据
XSSFSheet xssfSheet = xssfWorkbook.getSheetAt(activeSheetIndex);
//获取该页有多少行数据
int rowNum = xssfSheet.getLastRowNum();
//处理列名数据、自动转化表格标题名为列名
List<WorkBookTitleVO> workBookTitleVOS = analysisWorkBookForXlsx(xssfSheet);
//遍历列表中的每一行数据,并将之封装为JSONObject对象
for(int i = 1; i <= rowNum; i++) {
// 获取第i行数据
XSSFRow xssfRow = xssfSheet.getRow(i);
JSONObject obj = new JSONObject();
workBookTitleVOS.forEach(vo -> {
// 将所有字段都默认以字符串的格式读取
xssfRow.getCell(vo.getCellIndex()).setCellType(CellType.STRING);
obj.put(vo.getColumnName(), xssfRow.getCell(vo.getCellIndex()).toString());
});
resultList.add(obj);
}
} catch (IOException e) {
log.error("Xlsx文件解析异常,requestId:{},message:{}", requestId, e.getMessage());
}
return resultList;
}
/**
* 读取csv文件
* @param requestId
* @param in
* @return
*/
private static List<JSONObject> readCsvFile(String requestId, InputStream in) {
List<JSONObject> resultList = new ArrayList<>();
InputStreamReader reader = new InputStreamReader(in);
CSVReader csvReader = new CSVReader(reader);
List<String[]> list = null;
try {
//将InputStream转XLSX对象(即表格对象)
list = csvReader.readAll();
//处理列名数据、自动转化表格标题名为列名
List<WorkBookTitleVO> workBookTitleVOS = analysisWorkBookForCsv(list);
//遍历列表中的每一行数据,并将之封装为JSONObject对象
for(int i = 1; i < list.size(); i++) {
// 获取第i行数据
String[] csvRow = list.get(i);
JSONObject obj = new JSONObject();
workBookTitleVOS.forEach(vo -> {
obj.put(vo.getColumnName(), csvRow[vo.getCellIndex()]);
});
resultList.add(obj);
}
} catch (IOException e) {
log.error("Xlsx文件解析异常,requestId:{},message:{}", requestId, e.getMessage());
}
return resultList;
}
/**
* 分析xls文件选中页表格标题栏
* @return
*/
private static List<WorkBookTitleVO> analysisWorkBookForXls(HSSFSheet hssfSheet) {
// 获取该页有多少列数据
int cellNum = hssfSheet.getRow(0).getPhysicalNumberOfCells();
// 遍历取出每一列的第一行数据作为标题存入集合中
List<WorkBookTitleVO> titleList = new ArrayList<>();
for(int i = 0; i < cellNum; i++) {
// 取出第一行数据
HSSFRow hssfRow = hssfSheet.getRow(0);
// 存入表格title实体类中
WorkBookTitleVO vo = new WorkBookTitleVO();
vo.setCellIndex(i);
vo.setColumnName(hssfRow.getCell(i).toString());
titleList.add(vo);
}
return titleList;
}
/**
* 分析xlsx文件选中页表格标题栏
* @return
*/
private static List<WorkBookTitleVO> analysisWorkBookForXlsx(XSSFSheet xssfSheet) {
// 获取该页有多少列数据
int cellNum = xssfSheet.getRow(0).getPhysicalNumberOfCells();
// 遍历取出每一列的第一行数据作为标题存入集合中
List<WorkBookTitleVO> titleList = new ArrayList<>();
for(int i = 0; i < cellNum; i++) {
// 取出第一行数据
XSSFRow xssfRow = xssfSheet.getRow(0);
// 存入表格title实体类中
WorkBookTitleVO vo = new WorkBookTitleVO();
vo.setCellIndex(i);
vo.setColumnName(xssfRow.getCell(i).toString());
titleList.add(vo);
}
return titleList;
}
/**
* 分析csv文件选中页表格标题栏
* @return
*/
private static List<WorkBookTitleVO> analysisWorkBookForCsv(List<String[]> list) {
// 获取该页有多少列数据
int cellNum = list.get(0).length;
// 遍历取出每一列的第一行数据作为标题存入集合中
List<WorkBookTitleVO> titleList = new ArrayList<>();
for(int i = 0; i < cellNum; i++) {
// 取出第一行数据
String[] row = list.get(0);
// 存入表格title实体类中
WorkBookTitleVO vo = new WorkBookTitleVO();
vo.setCellIndex(i);
vo.setColumnName(row[i]);
titleList.add(vo);
}
return titleList;
}
}
表格标题实体类(转化表格标题使用)
package com.muyichen.demo.vo;
import lombok.Data;
import java.io.Serializable;
/**
* 表格实体类
* @author muyichen
* @version 1.0
*/
@Data
public class WorkBookTitleVO implements Serializable {
/**
* sheet页数
*/
private Integer sheetPage;
/**
* 列名
*/
private String columnName;
/**
* 列名所对应的表格列数
*/
private Integer cellIndex;
}
3、使用方式和结果
测试模版类
package com.muyichen.demo.vo;
import lombok.Data;
import java.io.Serializable;
/**
* 测试模版类
* @author muyichen
* @version 1.0
*/
@Data
public class model implements Serializable {
private Long id;
private String name;
private String video;
private String upImage;
private String downImage;
}
测试表格
测试方法
public static void main(String[] args) {
File file = new File("/Users/muyichen/Documents/model.xlsx");
ExcelUtil<Model> excelUtil = new ExcelUtil<>();
List<Model> models = excelUtil.excelReadForFile(file, Model.class);
System.out.println("==============");
}
测试结果