chinabugotech/hutool · error · IORuntimeException
Can't compare directories, only files
Error message
Can't compare directories, only files
What it means
FileUtil.contentEquals(File, File) compares two files byte-for-byte. It deliberately refuses directories because directory content comparison is undefined, throwing IORuntimeException("Can't compare directories, only files") if either argument is a directory (both must exist to reach this check).
Source
Thrown at hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java:1498
* @param file2 文件2
* @return 两个文件内容一致返回true,否则false
* @throws IORuntimeException IO异常
* @since 4.0.6
*/
public static boolean contentEquals(File file1, File file2) throws IORuntimeException {
boolean file1Exists = file1.exists();
if (file1Exists != file2.exists()) {
return false;
}
if (false == file1Exists) {
// 两个文件都不存在,返回true
return true;
}
if (file1.isDirectory() || file2.isDirectory()) {
// 不比较目录
throw new IORuntimeException("Can't compare directories, only files");
}
if (file1.length() != file2.length()) {
// 文件长度不同
return false;
}
if (equals(file1, file2)) {
// 同一个文件
return true;
}
InputStream input1 = null;
InputStream input2 = null;
try {
input1 = getInputStream(file1);
input2 = getInputStream(file2);
return IoUtil.contentEquals(input1, input2);View on GitHub (pinned to 8870454b2a)
Solutions
- Guard both arguments with FileUtil.isFile() before calling.
- Filter directory listings to regular files before comparing.
- If you need directory comparison, implement your own recursive walk comparing file sets.
Example fix
// before
boolean same = FileUtil.contentEquals(a, b); // throws if either is a dir
// after
if (FileUtil.isFile(a) && FileUtil.isFile(b)) {
boolean same = FileUtil.contentEquals(a, b);
} Defensive patterns
Strategy: validation
Validate before calling
if (FileUtil.isFile(file1) && FileUtil.isFile(file2)) {
return FileUtil.contentEquals(file1, file2);
}
return false; Type guard
static boolean bothRegularFiles(File a, File b) {
return a != null && b != null && a.isFile() && b.isFile();
} Try / catch
try {
return FileUtil.contentEquals(a, b);
} catch (IORuntimeException e) {
// one of them was a directory: skip or compare differently
} Prevention
- Filter to regular files before comparing contents.
- Skip directories when walking and comparing directory trees.
- Resolve and check both paths exist as files before the call.
When it happens
Trigger: Calling FileUtil.contentEquals where file1 or file2 is an existing directory.
Common situations: Comparing a directory against a file; iterating a folder's children and passing a subdirectory by accident; user input that resolves to a folder.
Related errors
AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14).
Data as JSON: /api/errors/54a7a305595b3d6d.
Report an issue: GitHub.