我正在比较junit中的文本文件:
public static void assertReaders(BufferedReader expected, BufferedReader actual) throws IOException { String line; while ((line = expected.readLine()) != null) { assertEquals(line, actual.readLine()); } assertNull("Actual had more lines then the expected.", actual.readLine()); assertNull("Expected had more lines then the actual.", expected.readLine()); }
这是比较文本文件的好方法吗?什么是首选?
这是检查文件是否完全相同的一种简单方法:
assertEquals("The files differ!", FileUtils.readFileToString(file1, "utf-8"), FileUtils.readFileToString(file2, "utf-8"));
其中file1
和file2
是File
实例,FileUtils
来自Apache Commons IO.
没有太多自己的代码供您维护,这总是一个加号.:)如果您已经在项目中使用Apache Commons,那么非常简单.但没有像mark的解决方案那样好的,详细的错误消息.
编辑:
嘿,仔细看看FileUtils
API,有一个更简单的方法:
assertTrue("The files differ!", FileUtils.contentEquals(file1, file2));
作为奖励,此版本适用于所有文件,而不仅仅是文本.
junit-addons对它有很好的支持:FileAssert
它为您提供以下例外:
junitx.framework.ComparisonFailure: aa Line [3] expected: [b] but was:[a]
以下是各种第三方Java库中文件比较器的更详尽列表:
org.apache.commons.io.FileUtils
org.dbunit.util.FileAsserts
org.fest.assertions.FileAssert
junitx.framework.FileAssert
org.springframework.batch.test.AssertFile
org.netbeans.junit.NbTestCase
org.assertj.core.api.FileAssert
截至2015年,我会推荐AssertJ,一个优雅而全面的断言库.对于文件,您可以断言另一个文件:
@Test public void file() { File actualFile = new File("actual.txt"); File expectedFile = new File("expected.txt"); assertThat(actualFile).hasSameContentAs(expectedFile); }
或者反对内联字符串:
@Test public void inline() { File actualFile = new File("actual.txt"); assertThat(linesOf(actualFile)).containsExactly( "foo 1", "foo 2", "foo 3" ); }
失败消息也非常有用.如果一条线不同,你得到:
java.lang.AssertionError: File:and file: do not have equal content: line:<2>, Expected :foo 2 Actual :foo 20
如果其中一个文件包含更多行:
java.lang.AssertionError: File:and file: do not have equal content: line:<4>, Expected :EOF Actual :foo 4
我建议使用Assert.assertThat和一个hamcrest匹配器(junit 4.5或更高版本 - 甚至可能是4.4).
我最终会得到类似的东西:
assertThat(fileUnderTest, containsExactText(expectedFile));
我的匹配器在哪里:
class FileMatcher { static MatchercontainsExactText(File expectedFile){ return new TypeSafeMatcher (){ String failure; public boolean matchesSafely(File underTest){ //create readers for each/convert to strings //Your implementation here, something like: String line; while ((line = expected.readLine()) != null) { Matcher> equalsMatcher = CoreMatchers.equalTo(line); String actualLine = actual.readLine(); if (!equalsMatcher.matches(actualLine){ failure = equalsMatcher.describeFailure(actualLine); return false; } } //record failures for uneven lines } public String describeFailure(File underTest); return failure; } } } }
Matcher职业选手:
组成和重用
在普通代码中使用以及测试
集合
用于模拟框架
可以使用一般谓词函数
非常好的日志能力
可与其他匹配器和描述结合使用,故障描述准确,精确
缺点:
嗯,这很明显吧?这比assert或junitx更冗长(对于这个特殊情况)
您可能需要包含hamcrest库以获得最大收益
FileUtils
肯定是一个很好的.这是检查文件是否完全相同的另一种简单方法.
assertEquals(FileUtils.checksumCRC32(file1), FileUtils.checksumCRC32(file2));
虽然assertEquals()确实提供了比assertTrue()更多的反馈,但checksumCRC32()的结果很长.所以,这可能没有内在的帮助.
Simpel使用java.nio.file API比较两个文件的内容.
byte[] file1Bytes = Files.readAllBytes(Paths.get("Path to File 1")); byte[] file2Bytes = Files.readAllBytes(Paths.get("Path to File 2")); String file1 = new String(file1Bytes, StandardCharsets.UTF_8); String file2 = new String(file2Bytes, StandardCharsets.UTF_8); assertEquals("The content in the strings should match", file1, file2);
或者,如果您想比较各个行:
Listfile1 = Files.readAllLines(Paths.get("Path to File 1")); List file2 = Files.readAllLines(Paths.get("Path to File 2")); assertEquals(file1.size(), file2.size()); for(int i = 0; i < file1.size(); i++) { System.out.println("Comparing line: " + i) assertEquals(file1.get(i), file2.get(i)); }