筆記:使用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
英文地址,請注明出處:http://en.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;更成為賦能企業開拓…