0.以终为始
easyexcel 文件导入,隐形字符串,导致Long类型转换失败。
1.问题背景
今天产品反馈一个问题,用户通过excel导入失败。这个excel只有一个用户id:202903294。使用阿里的easyexcel,类对象属性为
@ExcelProperty(value = "User ID")
private Long uid;
2.排查
2.1 异常信息
通过测试环境复现,查看异常日志。关键信息如下:
Convert data com.alibaba.excel.metadata.data.ReadCellData@9927c365 to class java.lang.Long error
com.alibaba.excel.exception.ExcelDataConvertException: Convert data com.alibaba.excel.metadata.data.ReadCellData@9927c365 to class java.lang.Long error
at com.alibaba.excel.util.ConverterUtils.doConvertToJavaObject(ConverterUtils.java:155) ~[easyexcel-3.0.5.jar!/:?]
at com.alibaba.excel.util.ConverterUtils.convertToJavaObject(ConverterUtils.java:100) ~[easyexcel-3.0.5.jar!/:?]
at com.alibaba.excel.read.listener.ModelBuildEventListener.buildUserModel(ModelBuildEventListener.java:103) ~[easyexcel-3.0.5.jar!/:?]
at com.alibaba.excel.read.listener.ModelBuildEventListener.invoke(ModelBuildEventListener.java:41) ~[easyexcel-3.0.5.jar!/:?]
at com.alibaba.excel.read.listener.ModelBuildEventListener.invoke(ModelBuildEventListener.java:26) ~[easyexcel-3.0.5.jar!/:?]
at com.alibaba.excel.read.processor.DefaultAnalysisEventProcessor.dealData(DefaultAnalysisEventProcessor.java:99) ~[easyexcel-3.0.5.jar!/:?]
at com.alibaba.excel.read.processor.DefaultAnalysisEventProcessor.endRow(DefaultAnalysisEventProcessor.java:46) ~[easyexcel-3.0.5.jar!/:?]
at com.alibaba.excel.analysis.v07.handlers.RowTagHandler.endElement(RowTagHandler.java:46) ~[easyexcel-3.0.5.jar!/:?]
at com.alibaba.excel.analysis.v07.handlers.sax.XlsxRowHandler.endElement(XlsxRowHandler.java:91) ~[easyexcel-3.0.5.jar!/:?]
Caused by: java.lang.NumberFormatException: For input string: "202903294"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) ~[?:1.8.0_302]
at java.lang.Long.parseLong(Long.java:589) ~[?:1.8.0_302]
at java.lang.Long.valueOf(Long.java:803) ~[?:1.8.0_302]
at com.alibaba.excel.util.NumberUtils.parseLong(NumberUtils.java:92) ~[easyexcel-3.0.5.jar!/:?]
at com.alibaba.excel.converters.longconverter.LongStringConverter.convertToJavaData(LongStringConverter.java:33) ~[easyexcel-3.0.5.jar!/:?]
at com.alibaba.excel.converters.longconverter.LongStringConverter.convertToJavaData(LongStringConverter.java:18) ~[easyexcel-3.0.5.jar!/:?]
at com.alibaba.excel.converters.Converter.convertToJavaData(Converter.java:57) ~[easyexcel-3.0.5.jar!/:?]
at com.alibaba.excel.util.ConverterUtils.doConvertToJavaObject(ConverterUtils.java:153) ~[easyexcel-3.0.5.jar!/:?]
2.2 初步判定
通过简单java代码,发现可以正常解析。
String uid="202903294";
System.out.println(Long.parseLong(uid));
System.out.println(Long.valueOf(uid));
初步判定是easyexcel的bug,或者是使用方法的问题。
2.3 最终结论
通过本地debug,最终发现异常。发现导入的用户id长度为10,异常的错误里面还多了一个引号。
发现这个字符串有问题,就想把它单独拷贝出来,看看什么情况。没想到一下就发现了问题。
再excel,聊天软件和chatgpt中,都是正常的。
现在已经确定了就是字符串的问题。隐形的字符串。
2.4 问题拓展
隐形字符究竟是什么问题,看看chatgpt的回答。
3.问题解决
使用正则表达式 [\p{C}] 匹配并去除所有不可见字符和控制字符。
public static void main(String[] args) {
//String uid1=202903294;
String uid = "202903294\u2063";
String uidNew = sanitizeString(uid);
System.out.println(Long.parseLong(uidNew));
//System.out.println(Long.parseLong(uid));
}
private static String sanitizeString(String str) {
// 去除不可见字符和控制字符
return str.replaceAll("[\\p{C}]", "");
}