java中的接口是类吗
482
2022-11-04
文本文件utf-8 bom编码导致内容读取乱码和无法比较匹配
spring boot项目中,有些配置,我不愿意正正经经,规规矩矩地写一个配置实体类来读取,那样要写不少代码,颇费周折,就想简单地通过文件读取的方式,将内容读进来,然后解释、处理。于是用记事本创建了一个.txt文件。内容有汉字,读取出来之后,做一些查找、匹配操作(indexOf()),结果失败。
究其原因,首先我读取文件的时候,用的是“ISO-8859-1”编码,然后项目默认编码是“UTF-8”,所以读取出来,当然比较失败;但将读取内容转化成“UTF-8”时,第一行的结果仍然比较失败,而后面的则正常。最后发现,该配置文件的编码方式为"UTF-8 BOM",文件开头多了3个特殊字节,所以第一行就比较失败了。
UTF-8 BOM其实是一种特殊的UTF-8,跟UTF-8编码文件的唯一不同,是在文件开头加入了一个3字节的特殊标记,用于指定每个字对应的数据在内存地址中存放顺序,即俗称的大端小端。大端模式,数据的高字节保存在内存的低地址,而数据的低字节保存在内存的高地址中。小端模式则相反。但是,无BOM(byte-order mark,字节顺序)的UTF-8才是标准的,UTF-8里塞入一个BOM只是微软的习惯用法。也因此,这个文本文件qj.txt我在intellij idea里编辑,是纯的utf-8编码;用记事本打开,修改了一下,就变成utf-8 bom编码了。
由于BOM只在文件开头,所以第一行数据比较失败,后面的则正常。
读取代码如下:
//读取文件内容,返回由行组成的数组private ArrayList _getAllQj(){ ArrayList lines = new ArrayList(); try{ String path = ResourceUtils.getURL("classpath:").getPath(); path = URLDecoder.decode(path, "utf-8"); path = String.format("%s\\qj.txt",path); /* RandomAccessFile(),默认编码是用"ISO-8859-1" */ RandomAccessFile raf = new RandomAccessFile(path, "r");//只读方式读文件 String line = raf.readLine(); while(line != null){ lines.add(line); line = raf.readLine(); } raf.close(); } catch(Exception ex){ } return lines;}//比较与匹配public String getQj(String name) { String url = ""; ArrayList lines = _getAllQj();//读取文件内容,返回由行组成的数组 for(Object obj : lines){ String line = obj.toString(); String[] values = line.split(",");//侠客岛, try { /* name2,表面上看值为“侠客岛”,但它前面多出了3个字节!导致后面的indexOf()失败 */ String name2 = new String(values[0].getBytes("ISO-8859-1"),"UTF-8"); //name = “侠客岛管理委员会” if(name.indexOf(name2) >= 0) {//结果是false! url = values[1]; break; } } catch(Exception ex){ } } return (url.length() > 0) ? "redirect:" + url : url;}
知道了问题所在就可以想好如何应对。可以将文件转回标准的utf-8编码,也可以在第一行写上不参与比较的注释,最好用英文,以避开这个雷区。
每当代码中需要用汉字来做配置或比较时,我都有点担心,担心在哪个环节不小心就会出问题。这编码那编码。这个问题,从20、30年前我接触电脑时就存在,到了今天,这个问题仍然是个坑,不小心就会掉进去。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~