这里是我的Java 7解决方案,适用于已知父路径和相对子路径可能与磁盘路径不同的情况。
例如,给定的文件/tmp/foo/biscuits
,该方法将正确地返回一个Path
到文件具有以下输入:
/tmp
和foo/biscuits
/tmp
和foo/BISCUITS
/tmp
和FOO/BISCUITS
/tmp
and FOO/biscuits
请注意,此解决方案有而不是已经过严格测试,因此应该将其视为起点而非生产就绪片段。
/**
* Returns an absolute path with a known parent path in a case-insensitive manner.
*
* <p>
* If the underlying filesystem is not case-sensitive or <code>relativeChild</code> has the same
* case as the path on disk, this method is equivalent to returning
* <code>parent.resolve(relativeChild)</code>
* </p>
*
* @param parent parent to search for child in
* @param relativeChild relative child path of potentially mixed-case
* @return resolved absolute path to file, or null if none found
* @throws IOException
*/
public static Path getCaseInsensitivePath(Path parent, Path relativeChild) throws IOException {
// If the path can be resolved, return it directly
if (isReadable(parent.resolve(relativeChild))) {
return parent.resolve(relativeChild);
}
// Recursively construct path
return buildPath(parent, relativeChild);
}
private static Path buildPath(Path parent, Path relativeChild) throws IOException {
return buildPath(parent, relativeChild, 0);
}
/**
* Recursively searches for and constructs a case-insensitive path
*
* @param parent path to search for child
* @param relativeChild relative child path to search for
* @param offset child name component
* @return target path on disk, or null if none found
* @throws IOException
*/
private static Path buildPath(Path parent, Path relativeChild, int offset) throws IOException {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(parent)) {
for (Path entry : stream) {
String entryFilename = entry.getFileName().toString();
String childComponent = relativeChild.getName(offset).toString();
/*
* If the directory contains a file or folder corresponding to the current component of the
* path, either return the full path (if the directory entry is a file and we have iterated
* over all child path components), or recurse into the next child path component if the
* match is on a directory.
*/
if (entryFilename.equalsIgnoreCase(childComponent)) {
if (offset == relativeChild.getNameCount() - 1 && Files.isRegularFile(entry)) {
return entry;
}
else if (Files.isDirectory(entry)) {
return buildPath(entry, relativeChild, offset + 1);
}
}
}
}
// No matches found; path can't exist
return null;
}
是的,这是一个可能性,但如果路径中的目录是错误的情况下问题仍然存在。该解决方案可能最终会成为某种递归算法,它会在目录树上执行不区分大小写的搜索。但我希望有更好的解决方案! – jwaddell 2009-08-19 05:06:59
@jwaddell:我不认为有更好的解决方案,因为文件名/路径可以在任何shell中,并且linux操作系统将其视为区分大小写的模式。 – 2009-08-19 05:20:48
看起来我会不情愿地实施这个解决方案,加上递归路径检查。 – jwaddell 2009-08-19 22:34:30