笔记:使用EasyExcel导入csv文件出现编码问题,导致导入数据全为null的解决方法

笔记:使用EasyExcel导入csv文件出现编码问题,导致导入数据全为null的解决方法

通常情况下,我们使用excel导入,但是部分情况下或者领导要求,我们需要使用csv导入文件,但是csv文件模板下载之后会变成系统当前编码,而不是固定为UTF-8,如果用excel的方式打开,写入数据之后,会提示你另存为xlsx,这也说明了csv和xlsx本质是完全不同的文件。
在这里插入图片描述
如果这种时候你使用EasyExcel默认的编码读取csv文件,你会发现读取的数据全部都是null,因为通常情况下,windows系统如果不特意设置编码格式,默认都为GBK,所以会导致导入数据无法读取的情况,当然excel并不会出现这种问题,所以如果不是特殊需求,导入还是推荐使用Excel文件。

这里分享一个导入方法,通过人为干预导入数据的方式,去判断是否读取成功,这里只用中国常用的UTF8GBK作为读取的编码,通常情况下是够用的,如果有需要,可以在charsets集合自行增加其他编码。

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.hexin.fms.common.excel.*;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.web.multipart.MultipartFile;import java.io.InputStream;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;public class ExcelUtil {/*** 多编码转换导入数据* 目前使用常用编码utf8和gbk解析文件* 如使用csv导入出现编码问题的时候* @param file 导入文件* @param clazz 类对象* @param excelTypeEnum 导入文件类型* @return 文件数据*/public static <T> ExcelResult<T> importExcelByAnyCharset(MultipartFile file, Class<T> clazz, ExcelTypeEnum excelTypeEnum) throws Exception {DefaultExcelListener<T> listener = new DefaultExcelListener<>(false);return importExcelByAnyCharset(file, clazz, excelTypeEnum, listener);}/*** 多编码转换导入数据* 目前使用常用编码utf8和gbk解析文件* 如使用csv导入出现编码问题的时候* @param file 导入文件* @param clazz 类对象* @param excelTypeEnum 导入文件类型* @param listener 监听器* @return 文件数据*/public static <T> ExcelResult<T> importExcelByAnyCharset(MultipartFile file, Class<T> clazz, ExcelTypeEnum excelTypeEnum,ExcelListener<T> listener) throws Exception {//需要校验的全部编码List<Charset> charsets = new ArrayList<>();charsets.add(StandardCharsets.UTF_8);charsets.add(Charset.forName("GBK"));//开始解析文件ExcelResult<T> result = new DefaultExcelResult<>();for(Charset charset : charsets){result = importExcelByCharset(file.getInputStream(), clazz, excelTypeEnum, listener, charset);//校验实体数据是否全部为nullif(result != null && result.getList() != null){List<T> resultList = result.getList();int size = resultList.size();int nullNums = 0;for(T t : resultList){if(t == null){nullNums++;continue;}Class<?> tClass = t.getClass();Field[] fields = tClass.getDeclaredFields();int len = fields.length;int fieldNullNums = 0;for(Field field : fields){field.setAccessible(true);if(field.get(t) == null){fieldNullNums++;}}if(len == fieldNullNums){nullNums++;}else{break;}}if(nullNums != size){break;}}}return result;}/*** 获取导入数据* 只走utf8,不校验获取数据是否为null* 如果不能保证导入文件为utf8,请使用importExcelByAnyCharset方法* @param is 导入文件的文件流* @param clazz 类对象* @param excelTypeEnum 导入文件类型* @return 文件数据*/public static <T> ExcelResult<T> importExcelByUTF8(InputStream is, Class<T> clazz, ExcelTypeEnum excelTypeEnum) {DefaultExcelListener<T> listener = new DefaultExcelListener<>(false);return importExcelByCharset(is, clazz, excelTypeEnum, listener, StandardCharsets.UTF_8);}/*** 获取导入数据* @param is 导入文件的文件流* @param clazz 类对象* @param excelTypeEnum 导入文件类型* @param listener 监听器* @param charset 用于导入文件数据转换的编码* @return 文件数据*/public static <T> ExcelResult<T> importExcelByCharset(InputStream is, Class<T> clazz, ExcelTypeEnum excelTypeEnum,ExcelListener<T> listener, Charset charset) {EasyExcel.read(is, clazz, listener).excelType(excelTypeEnum).charset(charset).sheet().doRead();return listener.getExcelResult();}
}

下面是一个默认的监听器,其中isValidate可以去掉,个人不建议在监听器里面作校验,这样导入数据之间的唯一性或者其他一些关系可能无法校验或者校验起来很麻烦。

个人建议,还是先获取到表格数据,然后再进行校验。

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelAnalysisException;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.hexin.fms.common.utils.JsonUtils;
import com.hexin.fms.common.utils.StreamUtils;
import com.hexin.fms.common.utils.ValidatorUtils;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Map;
import java.util.Set;@Slf4j
@NoArgsConstructor
public class DefaultExcelListener<T> extends AnalysisEventListener<T> implements ExcelListener<T> {/*** 是否Validator检验,默认为是*/private Boolean isValidate = Boolean.TRUE;/*** excel 表头数据*/private Map<Integer, String> headMap;/*** 导入回执*/private ExcelResult<T> excelResult;public DefaultExcelListener(boolean isValidate) {this.excelResult = new DefaultExcelResult<>();this.isValidate = isValidate;}/*** 处理异常** @param exception ExcelDataConvertException* @param context   Excel 上下文*/@Overridepublic void onException(Exception exception, AnalysisContext context) throws Exception {String errMsg = null;if (exception instanceof ExcelDataConvertException) {// 如果是某一个单元格的转换异常 能获取到具体行号ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException) exception;Integer rowIndex = excelDataConvertException.getRowIndex();Integer columnIndex = excelDataConvertException.getColumnIndex();errMsg = StrUtil.format("第{}行-第{}列-表头{}: 解析异常<br/>",rowIndex + 1, columnIndex + 1, headMap.get(columnIndex));if (log.isDebugEnabled()) {log.error(errMsg);}}if (exception instanceof ConstraintViolationException) {ConstraintViolationException constraintViolationException = (ConstraintViolationException) exception;Set<ConstraintViolation<?>> constraintViolations = constraintViolationException.getConstraintViolations();String constraintViolationsMsg = StreamUtils.join(constraintViolations, ConstraintViolation::getMessage, ", ");errMsg = StrUtil.format("第{}行数据校验异常: {}", context.readRowHolder().getRowIndex() + 1, constraintViolationsMsg);if (log.isDebugEnabled()) {log.error(errMsg);}}excelResult.getErrorList().add(errMsg);throw new ExcelAnalysisException(errMsg);}@Overridepublic void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {this.headMap = headMap;log.debug("解析到一条表头数据: {}", JsonUtils.toJsonString(headMap));}@Overridepublic void invoke(T data, AnalysisContext context) {if (isValidate) {ValidatorUtils.validate(data);}excelResult.getList().add(data);}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {log.debug("所有数据解析完成!");}@Overridepublic ExcelResult<T> getExcelResult() {return excelResult;}}

用法如下:

    @PostMapping(value = "/importExcel", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)public R<Void> importExcel(@RequestPart("file") MultipartFile file) throws Exception {ExcelResult<ImportVo> result = ExcelUtil.importExcelByAnyCharset(file, ImportVo.class, ExcelTypeEnum.CSV);List<ImportVo> excelList = result.getList();return importService.importExcel(excelList);}

importService.importExcel(excelList)就是你校验和保存更新删除数据的方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/86544.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/86544.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NL2SQL(Natural Language to SQL)优化之道:提升准确率与复杂查询能力

自然语言 → SQL 的转译&#xff08;NL2SQL&#xff09;技术&#xff0c;是让非技术用户与数据库“对话”的桥梁。而在实际应用中&#xff0c;我们不仅需要“能转”&#xff0c;更要“转得准、转得全、转得快”。 一、什么是 NL2SQL&#xff1f; NL2SQL&#xff08;Natural La…

java中map的循环方式

什么是Map集合&#xff1f; Map是Java中的一个接口&#xff0c;它用于存储键-值对&#xff0c;并且键和值都可以是任意对象。它是Java集合框架中的一部分&#xff0c;并提供了一些方法来操作和访问Map中的元素。 Map中的每个键都是唯一的&#xff0c;这意味着不能使用相同的键…

python学习笔记(深度学习)

文章目录 1、概述2、学习内容2.1、pytorch 常见语法2.1.1、sum2.1.2、广播机制2.1.3、张量2.1.4、DataLoader 2.2、普通语法2.2.1、迭代器 1、概述 本篇博客用来记录&#xff0c;在深度学习过程中&#xff0c;常用的 python 语法内容 2、学习内容 2.1、pytorch 常见语法 2.…

力扣网C语言编程题:搜索二维矩阵(右上角->左下角解法)

一. 简介 上一篇文章关于"在二维数组中查找某个元素"的问题&#xff0c;提供了两种解题思路&#xff0c;文章如下&#xff1a; 力扣网C语言编程题&#xff1a;搜索二维矩阵的普通解法与二分查找法-CSDN博客 本文提供第三种解题思路&#xff1a;从左下角->右上角…

AI大模型流式输出,OkHttp Log拦截打印方案

背景&#xff1a; 使用okhttp框架进行网络访问时&#xff0c;一般会使用 HttpLoggingInterceptor 打印请求和响应的log。在使用okhttp访问AI大模型时&#xff0c;如果选择流式输出&#xff0c;那么响应的body数据使用的SSE技术&#xff0c;服务异步发送大模型生成的增量token&…

看数据世界的历史:全面梳理从关系库、大数据到AI时代的数据发展及展望

序章 在数据库不断发展的时代里&#xff0c;我们看到了关系型数据库&#xff08;RDB&#xff09;在一次次的数据演变过程中的占据王位&#xff0c;捍卫了胜利&#xff0c;像一个王朝更替下的“王权”的故事&#xff0c;精彩有趣。 本篇就来探讨下数据库的发展兴衰史&#xff0…

元宇宙与人工智能的融合:从虚拟世界到智能生态的IT新革命

文章目录 引言&#xff1a;前沿技术重塑数字交互体验一、元宇宙与AI融合的本质&#xff1a;虚拟空间与智能交互的交汇元宇宙赋能AI&#xff1a;AI赋能元宇宙&#xff1a; 二、元宇宙与AI融合的演进&#xff1a;从概念到产业热潮三、核心技术&#xff1a;元宇宙与AI融合的基石与…

问卷调查[mqtt dht]

任务 this code uses esp32-wroom-32 and dht11 to read the humidty and temperature, besieds, it will send the meassage to the cloud platform. All communication is conducted through MQTT. 打分标准 您应该对以下代码进行评级&#xff0c;并且必须遵守如…

swift 对象转Json

在 Swift 中将对象转换为 JSON 可以通过以下方法实现&#xff1a; 使用 Codable 协议 Swift 的 Codable 协议&#xff08;Encodable 和 Decodable 的组合&#xff09;是处理 JSON 编码和解码的推荐方式。 struct Person: Codable {var name: Stringvar age: Int }let person…

Python学习Day43

学习来源&#xff1a;浙大疏锦行 import torch import torch.nn as nn import torch.nn.functional as F import torchvision import torchvision.transforms as transforms import numpy as np import matplotlib.pyplot as plt from PIL import Image import os # 设置随机…

了解一下Unity AssetBundle 的几种加载方式

Unity 的 AssetBundle 系统提供了多种加载方式&#xff0c;以满足不同场景下的资源管理和性能需求。 同步加载&#xff08;LoadFromFile&#xff09; 同步加载使用 AssetBundle.LoadFromFile 方法从文件系统中直接加载 AssetBundle。这种方式会阻塞主线程&#xff0c;直到加载…

鸿蒙边缘智能计算架构实战:多线程图像采集与高可靠缓冲设计

目录 一、技术背景与挑战二、鸿蒙边缘计算架构的核心特性1. 分布式软总线&#xff1a;打破设备孤岛2. 轻量化多线程模型 三、多线程图像采集的稳定性设计1. 分层缓冲队列架构2. 线程优先级策略 四、边缘侧高可靠缓冲机制1. 基于分布式数据管理的容错设计2. 动态带宽调节 五、实…

excel中vba开发工具

1、支持单元格点击出现弹框进行选择 支持模多次模糊查询 Private Sub CommandButton1_Click() Call vehicle_查询 End SubPrivate Sub Worksheet_Activate()Call vehicle_取出车架号和公司名称 取出不重复的车架号Sheet13.ComboBox1.Visible False 车架号显示Sheet13.ComboB…

CatBoost:征服类别型特征的梯度提升王者

基于有序提升与对称树的下一代GBDT框架&#xff0c;重塑高维分类数据处理范式 一、CatBoost的诞生&#xff1a;解决类别特征的终极挑战 2017年由俄罗斯Yandex团队开源&#xff0c;CatBoost&#xff08;Categorical Boosting&#xff09;直指机器学习中的核心痛点&#xff1a;类…

使用 WSL 启动ubuntu.tar文件

使用 WSL 启动ubuntu.tar文件&#xff0c;可按以下步骤进行3&#xff1a; 检查 WSL 版本&#xff1a;确保你的 WSL 版本为 2.4.8 或更高版本。可以在命令行中输入wsl --update来更新 WSL 到最新版本。 设置默认 WSL 版本&#xff1a;如果还没有将 WSL 2 设置为默认版本&#x…

vue-23(创建用于逻辑提取的可重用组合组件)

创建用于逻辑提取的可重用组合组件 可重用的组合式是 Vue 组合式 API 的基石&#xff0c;它使你能够在多个组件中提取和重用有状态逻辑。这有助于编写更清晰的代码&#xff0c;减少冗余&#xff0c;并提高可维护性。通过将特定功能封装到组合式中&#xff0c;你可以轻松地共享…

数据透视表学习笔记

学习视频&#xff1a;Excel数据透视表大全&#xff0c;3小时从小白到大神&#xff01;_哔哩哔哩_bilibili 合并行标签 初始数据透视表 不显示分类汇总 以大纲形式显示 在组的底部显示所有分类汇总 以表格形式显示 合并单元格-右键-数据透视表选项 选中-合并并剧中排列带…

吃透 Golang 基础:测试

文章目录 go test测试函数随机测试测试一个命令白盒测试外部测试包 测试覆盖率基准测试剖析示例函数 go test go test命令是一个按照一定的约定和组织来测试代码的程序。在包目录内&#xff0c;所有以xxx_test.go为后缀名的源文件在执行go build时不会被构建为包的一部分&#…

酒店服务配置无门槛优惠券

1.查看酒店绑定的是那个仓库&#xff1b; 凯里亚德酒店(深圳北站壹城中心店)&#xff0c;绑定的是“龙华民治仓&#xff08;睿嘀购” 2.“门店列表”选择“龙华民治仓&#xff08;睿嘀购””中的“绑定场所” 3.通过酒店名字查找绑定的商品模板&#xff1b; 凯里亚德酒店(深圳…

IoT创新应用场景,赋能海外市场拓展

在数字化浪潮席卷全球的当下&#xff0c;物联网&#xff08;Internet of Things, IoT&#xff09;正以革命性的力量重塑产业生态。这项通过传感器、通信技术及智能算法实现设备互联的技术&#xff0c;不仅推动全球从“万物互联”迈向“万物智联”&#xff0c;更成为赋能企业开拓…