Java接收解析excel方法及注意事项说明
前言
提示:本文着重讲解java如何处理excel:
例如:本文从java接收excel,解析excel,以及业务场景中基于阻塞队列处理大批量的Excel。
提示:以下是本篇文章正文内容,下面案例可供参考
一、Java接收Excel
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
1.引入库
pom如下:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.21</version>
</dependency>2.Controller层代码
提示: 本文MultipartFile接收,请求方式为form表单提交
/**
* 传入excel
*
* @return
*/
@PostMapping(value = "/inputExcel", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ApiOperation("传入excel")
public R inputExcel(@RequestPart("file") MultipartFile file) {
InputExcelDTO inputExcelDTO = new InputExcelDTO();
inputExcelDTO.setFile(file);
if (Objects.isNull(inputExcelDTO.getExcelName()) || Objects.isNull(inputExcelDTO.getFile())) {
return R.failed("必填参数不可为空");
}
return excelService.inputExcel(inputExcelDTO);
}
二、解析excel
1.将MultipartFile 转 File作为临时文件存储在本地,解析
代码如下:
工具类 :
package com.byt.form.convert.util;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author: author
* @date: 2021/8/27 8:46
* @description: excel处理工具类
*/
public class ExcelDealUtils {
/**
* MultipartFile 转 File
*
* @param file
* @throws Exception
*/
public static File multipartFileToFile(MultipartFile file) throws Exception {
File toFile = null;
if (file.equals("") || file.getSize() <= 0) {
file = null;
} else {
InputStream ins = null;
ins = file.getInputStream();
toFile = new File(file.getOriginalFilename());
inputStreamToFile(ins, toFile);
ins.close();
}
return toFile;
}
//获取流文件
private static void inputStreamToFile(InputStream ins, File file) {
try {
OutputStream os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除本地临时文件
*
* @param file
*/
public static void deleteTempFile(File file) {
if (file != null) {
File del = new File(file.toURI());
del.delete();
}
}
/**
* 处理数据
*
* @param str
* @return
*/
public static String getDelDay(String str) {
str = str.trim();
String reg = "[\u4e00-\u9fa5]";
Pattern pat = Pattern.compile(reg);
Matcher mat = pat.matcher(str);
String repickStr = mat.replaceAll("");
return repickStr;
}
}
ServiceImpl实现层
File excel= ExcelDealUtils.multipartFileToFile(inputExcelDTO.getFile());
try {
//excel最后修改时间
String excelTime = modTime;
if (excel.isFile() && excel.exists()) { //判断文件是否存在
String[] split = excel.getName().split("\\."); //特殊字符转义
Workbook wb;
//根据文件后缀(xls/xlsx)进行判断
if ("xls".equals(split[split.length - 1])) {
FileInputStream fis = new FileInputStream(excel); //文件流对象
wb = new HSSFWorkbook(fis);
fis.close();
} else if (("xlsx".equals(split[split.length - 1]))) {
ZipSecureFile.setMinInflateRatio(-1.0d);
FileInputStream fis = new FileInputStream(excel);
wb = new XSSFWorkbook(fis);
fis.close();
} else {
log.info("文件类型错误");
return;
}
JSONArray data = new JSONArray();
if (sheet == null) {
return;
}
log.info("处理sheet为{}", sheet.getSheetName());
int firstRowIndex = sheet.getFirstRowNum(); //第一行是列名ABC...字母,所以不读
int lastRowIndex = sheet.getLastRowNum();
for (int rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) { //遍历行
JSONArray rowArray = new JSONArray();
Row row = sheet.getRow(rIndex);
if (row != null) { //这里只保存了不为空的行
int firstCellIndex = row.getFirstCellNum();
int lastCellIndex = row.getLastCellNum();
for (int cIndex = firstCellIndex; cIndex < lastCellIndex; cIndex++) { //遍历列
Cell cell = row.getCell(cIndex);
if (cell != null) {
rowArray.add(getCellFormatValue(cell));
} else {
rowArray.add("");
}
}
}
if (rowArray.size() > 5) {
data.add(rowArray);
}
}
//data为二维数组,顺序与excel一致
wb.close();
} else {
log.info("找不到指定文件");
}
} catch (Exception e) {
log.info("解析错误 报表id为{},错误日志为{}", excelId, e);
}
/**
* 处理公式数据,如果是公式直接读值,excel日期解析到的是数字,需要转换成日期
*根据项目情况处理
* @param cell
* @return
*/
public static Object getCellFormatValue(Cell cell) {
Object cellValue = null;
if (cell != null) {
//判断cell类型
switch (cell.getCellType()) {
case Cell.CELL_TYPE_NUMERIC: {
cell.setCellType(Cell.CELL_TYPE_STRING); //数字型特殊处理,使获取的整型不带有小数点
cellValue = cell.getRichStringCellValue().getString();
// cellValue = String.valueOf(cell.getNumericCellValue());
break;
}
case Cell.CELL_TYPE_FORMULA: {
//非法字符处理
try {
cellValue = cell.getStringCellValue();
} catch (Exception e) {
//特殊处理
}
try {
cellValue = String.valueOf(cell.getNumericCellValue());
} catch (Exception e) {
}
break;
}
case Cell.CELL_TYPE_STRING: {
cellValue = cell.getRichStringCellValue().getString();
break;
}
default:
cellValue = "";
}
} else {
cellValue = "";
}
return cellValue;
}
2.大批量的excel同时丢上来容易内存溢出,故用阻塞队列处理
全局参数:
// 能容纳100个文件
final BlockingQueue<File> queue = new LinkedBlockingQueue<File>(100);
// 读个数
final AtomicInteger rc = new AtomicInteger();
// final File exitFile = new File("");
HashMap<String, DelFileBO> fileMap = new HashMap<>();
存入阻塞队列:
/**
*存入阻塞队列
*/
private void (File file){
//存入Map,主要是为了避免线程同时处理多个,所以用map记录
fileMap.put(delFile.getName(), file);
//放入阻塞队列
scanFile(delFile);
}
public void scanFile(File file) {
if (file.isDirectory()) {
File[] files = file.listFiles(new FileFilter() {
public boolean accept(File pathname) {
return pathname.isDirectory()
|| pathname.getPath().endsWith(".java");
}
});
for (File one : files)
scanFile(one);
} else {
try {
int index = rc.incrementAndGet();
queue.put(file);
} catch (InterruptedException e) {
}
}
}
起一个线程从队列拿数据处理
@PostConstruct
public void delExcelFile() {
taskExecutor.execute(() -> {
while (true) {
this.delFile();
}
});
}
public void delFile() {
try {
//从队列拿文件处理
File file = queue.take();
//业务逻辑
} catch (InterruptedException e) {
}
}
总结
以上就是今天要讲的内容,本文仅仅简单介绍了java如何解析excel,针对自身业务也可以维护一些其余配置,如报表id以及处理方式等。
这些仅为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
SpringBoot Mybatis动态数据源切换方案实现过程
这篇文章主要介绍了SpringBoot+Mybatis实现动态数据源切换方案过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下2020-04-04
java DataInputStream和DataOutputStream详解及实例代码
这篇文章主要介绍了java DataInputStream和DataOutputStream详解及实例代码的相关资料,需要的朋友可以参考下2017-01-01


最新评论