使用Files.readAllBytes对比文件字节数组失败,逐行对比正常的原因?
文件字节数组对比失败,但IDE显示一致、逐行对比通过的原因
问题描述
我通过以下代码对比两个文件的字节数组,结果验证失败:
byte[] expectedContent = Files.readAllBytes(expectedPath); byte[] generatedContent = Files.readAllBytes(generatedPath); Assertions.assertTrue(Arrays.equals(expectedContent, generatedContent), "Content not equal");
但IntelliJ显示两个文件完全一致(包括空白字符、格式等),且使用逐行对比的代码能正常通过:
Scanner input1 = new Scanner(new File(expectedPath.toString())); Scanner input2 = new Scanner(new File(generatedPath.toString())); while(input1.hasNextLine() && input2.hasNextLine()){ String first = input1.nextLine(); String second = input2.nextLine(); Assertions.assertTrue(first.equals(second), "Differences found: "+"\n"+first+'\n'+second); }
为什么会出现这种矛盾?Files.readAllBytes会读取文件元数据吗?
核心原因分析
- 换行符编码差异:不同系统的换行符字节不一样——Windows用
\r\n(对应字节0x0D 0x0A),Linux/macOS用\n(对应字节0x0A)。Scanner.nextLine()只返回行内的文本内容,会自动丢弃换行符本身,所以逐行对比时无法检测到这种差异;但Files.readAllBytes会读取文件的所有字节,包括换行符的不同编码,导致数组对比失败。而IntelliJ默认会统一渲染换行符,所以视觉上显示一致。 - 文件末尾的额外换行符/空行差异:其中一个文件末尾多了一个换行符(或空行),另一个没有。
Scanner.hasNextLine()在处理文件末尾的换行符时,不会将其识别为一个额外的空行;但字节数组会包含这个额外的换行符字节,直接导致对比不匹配。 - UTF-8 BOM(字节顺序标记)差异:如果其中一个文件开头带有UTF-8 BOM(字节
0xEF 0xBB 0xBF),另一个没有,Files.readAllBytes会读取到这个BOM字节;而Scanner在读取UTF-8编码的文件时会自动跳过BOM,逐行对比时不会体现这个差异,IDE也通常默认隐藏BOM的显示,导致看起来文件内容完全一致。 - 关于
Files.readAllBytes读取元数据的疑问:这个方法不会读取文件元数据(比如创建时间、权限、文件属性等),它只会读取文件的实际内容字节,所以元数据不是导致对比失败的原因。
内容的提问来源于stack exchange,提问作者Shakesbeer
相关产品推荐
相关产品推荐

