有时候写代码会遇到一些莫名其妙的问题,两个字符串明明toString()打印一模一样,但是equals就是为false。
直接看代码
public static void main(String[] args) { String s1 = 'helloworld'; String s2 = 'helloworld'; System.out.println(s1.equals(s2));}
这代码应该够简单了,毫无疑问输出true啊。但是我们还是实际操作一下:
其实这个问题很简单,因为字符串s1中包含了不可打印字符
,可以把两个字符串复制到 QQ/TIM 看一下就知道了,或者直接按F12审查元素也可以看到。或者我们继续在Java代码中查看
public static void main(String[] args) { String s1 = 'helloworld'; String s2 = 'helloworld'; System.out.println(s1.equals(s2)); System.out.println(Arrays.toString(s1.getBytes())); System.out.println(Arrays.toString(s2.getBytes()));}
说一个最常见的场景,window下新建一个test.txt文件(用window自带的记事本),随便写点什么,就“helloworld”吧。保存(另存为)的时候选择UTF-8编码。
EF BB BF
,用来标记这是一个UTF8编码的文件。程序读取文件时,会把BOM头一起读入内存:public static void compareContent() { InputStream is = null; try { is = new FileInputStream(new File('D:\\test.txt')); byte[] buff = new byte[16]; int nRead = 0; StringBuilder sb = new StringBuilder(); while ((nRead = is.read(buff)) != -1) { sb.append(new String(buff, 0, nRead)); } //UTF-8文件读取的字符串 String fileStr = sb.toString(); //程序定义的字符串,此处不包含不可打印字符 String localStr = 'helloworld'; System.out.println(fileStr.toString()); System.out.println(localStr.toString()); System.out.println('文件字符串:' + Arrays.toString(fileStr.getBytes())); System.out.println('本地字符串:' + Arrays.toString(localStr.getBytes())); } catch (IOException e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } }
运行结果如下:
如果文件非要以UTF-8编码保存,可以有以下几种方法:
public static String deleteUTF8Bom(String fileStr) { byte[] UTF8_BOM_BYTES = new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF}; byte[] bytes = fileStr.getBytes(); if (bytes[0] == UTF8_BOM_BYTES[0] && bytes[1] == UTF8_BOM_BYTES[1] && bytes[2] == UTF8_BOM_BYTES[2]) { return new String(bytes, 3, bytes.length - 3); } return fileStr;}
这个问题不太容易发现,但是其实也是属于基础内容。也说明眼见不一定为实,看到的字符串不一定就是真正的字符串。
联系客服