ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【眼见不一定为实】HashMap的key和value明明存在,但是获取不到值

2021-12-19 01:33:58  阅读:139  来源: 互联网

标签:文件 UTF 字节 value 为实 BOM key csv HashMap


发现问题

事情是这样,最近在做一个微信支付对账功能,需要解析从微信下载回来的csv文件,发现解析出来交易时间为空。
去debug发现了一个很有意思的现象,上图:
image.png
image.png
image.png

出现的问题就是,同一个map,同样是全中文的key(为啥是中文key,因为微信返回来的账单就是中文),读取【交易时间】为空,读取【商户号】正常。so,why?

找到直接原因

我一顿操作猛如虎,找jdk源码debug了半天,一度怀疑是HashMap扩容导致了数据下标变了,然而实际上并非如此。。。。。。

后来无意中看到了一个被我忽略的细节,瞬间明朗。
image.png
其实问题就在于,map里面的key实际上是[\uFEFF交易时间],只不过\uFEFF这个字符显示不出来,导致我误认为是[交易时间],当我通过get(交易时间)去取值,当然拿不到,因为真正的key==[\uFEFF交易时间],key!=[交易时间]。
image.png

分析根本原因

好了,直接原因找到了,那继续深入排查根本原因。这个\uFEFF到底是个啥???叫做BOM。

BOM(Byte Order Mark),字节顺序标记,出现在文本文件头部,Unicode编码标准中用于标识文件是采用哪种格式的编码,但它对于文件的读者来说是不可见字符。
BOM定义:http://www.unicode.org/unicode/faq/utf_bom.html

因为Unicode可以采用16位或者32位编码,所以计算机在处理时需要知道其字节顺序,BOM就是用来标识字节流的字节顺序的,但字节顺序这个 概念对UTF-8来说是没有意义的,所以BOM对UTF-8同样没有意义。但Unicode标准BOM在UTF-8编码格式中存在,其存在位置在文件开 头,以三个字节0xEF, 0xBB, 0xBF表示。

UTF-8编码不推荐使用无意义的BOM,但许多Windows程序却在保存UTF-8编码的文件时将其存为带BOM的格式(即在文件开头加上0xEFBBBF三个字节),这么干的就包括Windows记事本。

因此,在编辑UTF-8的文件时,建议不要使用记事本等进行编辑,虽然保存后的文件仍然是UTF-8,但却已经不再是保存前的UTF-8了。

因为BOM存在于文件开头,而【交易时间】刚好就是第一个被读取的csv列,所以被读取到一块去了,导致了前面的此【交易时间】非彼【交易时间】。

用文本编辑器打开csv,其实也是看不到这个编码的,但我们可以发现这个csv文件的编码格式为【UTF-8 有签名】,也就是带了BOM标记。
image.png

解决方案

1、另存为一份无签名的UTF-8格式的csv

我们可以用第三方编辑器另存为一份无签名的UTF-8格式的csv,再试一下
image.png

image.png

2、去掉BOM头再读取

由于文件是自动从微信下载,不可能手工另存为,所以只能每次先去掉BOM头再读取数据。
由于我使用了hutool工具包,hutool封装了一个BOMInputStream,可以解决这个问题,所以我这里直接使用hutool工具处理。
image.png
这里注意一定要调用getCharset()方法才会自动去掉BOM头
image.png

标签:文件,UTF,字节,value,为实,BOM,key,csv,HashMap
来源: https://www.cnblogs.com/cheng-c/p/15706534.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有