测试两个目录树是否相等
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了测试两个目录树是否相等相关的知识,希望对你有一定的参考价值。
我正在进行集成测试,我的代码的一部分在SVN下创建目录树。这需要我测试目录结构和其中的文件是否是我期望的。
一方面,我有预期的目录树和我想要的文件,另一方面,从SVN导出文件(更喜欢svn export
而不是svn co
以避免.svn
噪音)。
但是,是否有任何库可以断言两个目录树?我想到的最后一招是我自己进行迭代比较。
基本上我正在寻找一个可以接受两个目录并告诉我它们是否相等的API。
有点像的东西
boolean areDirectoriesEqual(File dir1, File dir2)
我没有使用第三方lib而是使用标准的jdk lib。
private static void verifyDirsAreEqual(Path one, Path other) throws IOException {
Files.walkFileTree(one, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs)
throws IOException {
FileVisitResult result = super.visitFile(file, attrs);
// get the relative file name from path "one"
Path relativize = one.relativize(file);
// construct the path for the counterpart file in "other"
Path fileInOther = other.resolve(relativize);
log.debug("=== comparing: {} to {}", file, fileInOther);
byte[] otherBytes = Files.readAllBytes(fileInOther);
byte[] thisBytes = Files.readAllBytes(file);
if (!Arrays.equals(otherBytes, thisTypes)) {
throw new AssertionFailedError(file + " is not equal to " + fileInOther);
}
return result;
}
});
}
注意:这只是比较两个文件夹下的实际文件。如果你有空文件夹等也想要比较,你可能需要做一些额外的事情。
我不知道任何areDirsEqual
图书馆;我能想到的最接近的是Commons FileUtils
中的listFiles方法。
如果将结果集合放在HashSet
中,您应该能够有效地比较这两个集合。它可以在2行中完成,甚至可以是单行。
这方面的东西:
public static boolean areDirsEqual(File dir, File dir2) {
return (new HashSet<File>(FileUtils.listFiles(dir1,..))).
containsAll(FileUtils.listFiles(dir2, ..))
}
我遇到了同样的问题,继Patrick和LorenzoDematté后,我发现了一个适合我的解决方案。以下代码遍历文件夹并:
- 对于每个子文件夹,检查文件列表是否相同
- 为每个文件比较内容(在我的情况下,我必须比较两个包含csv文件的文件夹)
我在linux上测试过它。
private static void verifyDirsAreEqual(File expected, File generated)
throws IOException {
// Checks parameters
assertTrue("Generated Folder doesn't exist: " + generated,generated.exists());
assertTrue("Generated is not a folder?!?!: " + generated,generated.isDirectory());
assertTrue("Expected Folder doesn't exist: " + expected,expected.exists());
assertTrue("Expected is not a folder?!?!: " + expected,expected.isDirectory());
Files.walkFileTree(expected.toPath(), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs)
throws IOException {
FileVisitResult result = super.preVisitDirectory(dir, attrs);
// get the relative file name from path "expected"
Path relativize = expected.toPath().relativize(dir);
// construct the path for the counterpart file in "generated"
File otherDir = generated.toPath().resolve(relativize).toFile();
log.debug("=== preVisitDirectory === compare " + dir + " to " + otherDir);
assertEquals("Folders doesn't contain same file!?!?",
Arrays.toString(dir.toFile().list()),
Arrays.toString(otherDir.list()));
return result;
}
@Override
public FileVisitResult visitFile(Path file,
BasicFileAttributes attrs)
throws IOException {
FileVisitResult result = super.visitFile(file, attrs);
// get the relative file name from path "expected"
Path relativize = expected.toPath().relativize(file);
// construct the path for the counterpart file in "generated"
File fileInOther = generated.toPath().resolve(relativize).toFile();
log.debug("=== comparing: " + file + " to " + fileInOther);
String expectedContents = FileUtils.readFileToString(file.toFile());
String generatedContents = FileUtils.readFileToString(fileInOther);
assertEquals("("+fileInOther+") csv standard doesn't match expected ("+file+")!", expectedContents, generatedContents);
return result;
}
});
}
好的,所以我不知道任何准备好的代码那样做,搜索也没有帮助。所以这是我将如何实现它
- 以递归方式迭代所有文件夹和文件
- 使用hash中相对路径保存所有文件名,其中相对路径是键/值
- 在第二个目录结构上递归迭代并从每个路径创建一个匹配hashet中的键(如果文件夹/文件存在)
如果您只想将树标记为已更改/未更改,则可以保存每个文件的哈希值,然后需要哈希图而不是哈希集,其中每个文件内容的哈希值是哈希值的值
希望这可以帮助
这是一个使用Java NIO包的简单迭代解决方案(不使用Visitor模式,因此它也可以适用于早期的Java版本)。
当然它可以调整,但是现在这是一个简单的解决方案,从两个目录的视图检查是否每个文件都出现,并可选择使用Apache Commons FileUtils比较文件内容。
/**
* checks if the directory file lists and file content is equal
*
* @param directory
* the directory
* @param compareDirectory
* the directory to compare with
* @param checkFileContent
* also compare file content
* @return true if directory and compareDirectory are equal
* @throws IOException
*/
public static boolean isEqualDirectories(Path directory, Path compareDirectory, boolean checkFileContent) throws IOException {
boolean check = isEverythingInCompareDirectory(directory, compareDirectory, checkFileContent);
boolean checkOpposite = check && isEverythingInCompareDirectory(directory, compareDirectory, checkFileContent);
return check && checkOpposite;
}
/**
* checks if the directory file lists and file content is equal
*
* @param directory
* the directory
* @param compareDirectory
* the directory to compare with
* @param checkFileContent
* also compare file content
* @return true if directory and compareDirectory are equal
* @throws IOException
*/
public static boolean isEverythingInCompareDirectory(Path directory, Path compareDirectory, boolean checkFileContent)
throws IOException {
try {
LOGGER.info("checking directory " + directory);
File directoryFile = directory.toFile();
File compareFile = compareDirectory.toFile();
// check, if there is the same number of files/subdirectories
File[] directoryFiles = directoryFile.listFiles();
File[] compareFiles = compareFile.listFiles();
if (directoryFiles.length == compareFiles.length) {
return compareDirectoryContents(directory, compareDirectory, checkFileContent);
} else {
LOGGER.info("number of files in directory are different " + directoryFiles.length + " vs compareDirectory: " + compareFiles.length);
return false;
}
} catch (IOException e) {
throw new RuntimeException("Failed to assert that all files are equal", e);
}
}
public static boolean compareDirectoryContents(Path directory, Path compareDirectory, boolean checkFileContent) throws IOException {
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(directory)) {
for (Path directoryFilePath : directoryStream) {
// search for directoryFile in the compareDirectory
Path compareFilePath = compareDirectory.resolve(directoryFilePath.getFileName());
if (compareFilePath != null) {
File directoryFile = directoryFilePath.toFile();
if (directoryFile.isFile()) {
LOGGER.info("checking file " + directoryFilePath);
if (checkFileContent && !FileUtils.contentEquals(compareFilePath.toFile(), directoryFile)) {
LOGGER.info("files not equal: compare: " + compareFilePath.toFile() + ", directory: " + directoryFilePath.getFileName() + "!");
return false;
}
} else {
LOGGER.info("going into recursion with directory " + directoryFilePath);
bo以上是关于测试两个目录树是否相等的主要内容,如果未能解决你的问题,请参考以下文章