Java 对于Windows 10上的两个不同文件夹(小写m和大写m),Path.equals()返回true
我创建了一个文件索引器,它在Windows7和Ubuntu中运行良好 自从我迁移到Windows 10以来,我的代码一直在一个特定的文件夹上抛出错误,Java 对于Windows 10上的两个不同文件夹(小写m和大写m),Path.equals()返回true,java,windows,java-8,windows-10,windows-subsystem-for-linux,Java,Windows,Java 8,Windows 10,Windows Subsystem For Linux,我创建了一个文件索引器,它在Windows7和Ubuntu中运行良好 自从我迁移到Windows 10以来,我的代码一直在一个特定的文件夹上抛出错误,C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo 此文件夹是特殊的,因为它包含具有小写和大写名称的文件夹,如果使用小写,则名称相同 问题是我已经浏览了所有的代码库,它没有equalsIgnoreCase或toLowerCase或toupercase的实例 最后,我得出结论
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo
此文件夹是特殊的,因为它包含具有小写和大写名称的文件夹,如果使用小写,则名称相同
问题是我已经浏览了所有的代码库,它没有equalsIgnoreCase
或toLowerCase
或toupercase
的实例
最后,我得出结论,对于两个不同的文件夹,Path.equals
返回true,这是不应该的。这会在我的代码中引起问题,因为路径
被用作映射
关于代码中任何地方的键,特别是在我的索引器实现中,这会导致收集器。groupingBy
将属于不同文件夹的文件分组到同一文件夹中:
Map<Path, List<DetailedFileReference>> parentFolderToDetailList = finderResult.getDetails().stream()
.collect(Collectors.groupingBy(o -> o.asPathObject().getParent()));
此代码打印:
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\m is equal to C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\M
但是,其他Java代码确实看到了这两个文件夹之间的区别,因为Files.walk
可以正常工作:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public final class DuplicateFileIndexing {
public static void main(String[] args) throws IOException {
Path originFolder = Paths.get("C:\\Users\\Terminal\\AppData\\Local\\lxss\\rootfs\\usr\\share\\terminfo");
Path lowercaseFolder = originFolder.resolve("m");
Path uppercaseFolder = originFolder.resolve("M");
System.out.println(originFolder.toAbsolutePath().toString());
List<String> directoriesInOriginFolder = Files.walk(originFolder, 1)
.filter(path -> Files.isDirectory(path))
.map(path -> path.getFileName().toString())
.collect(Collectors.toList());
System.out.println(directoriesInOriginFolder);
if (directoriesInOriginFolder.contains("m")) {
System.out.println("Has a m folder");
}
if (directoriesInOriginFolder.contains("M")) {
System.out.println("Has a M folder");
}
System.out.println("---");
System.out.println("Files in 'm' folder");
Files.walk(lowercaseFolder, 1)
.map(path -> path.toAbsolutePath().toString())
.forEach(System.out::println);
System.out.println("---");
System.out.println("Files in 'M' folder");
Files.walk(uppercaseFolder, 1)
.map(path -> path.toAbsolutePath().toString())
.forEach(System.out::println);
System.out.println("---");
System.out.println("Parent of files in 'm' folder");
Files.walk(lowercaseFolder, 1)
.map(path -> path.toAbsolutePath().toString() + " is a child of " + path.getParent().toString())
.forEach(System.out::println);
System.out.println("---");
System.out.println("Parent of files in 'M' folder");
Files.walk(uppercaseFolder, 1)
.map(path -> path.toAbsolutePath().toString() + " is a child of " + path.getParent().toString())
.forEach(System.out::println);
System.out.println("---");
if (lowercaseFolder.equals(uppercaseFolder)) {
System.out.println(lowercaseFolder.toString() + " is equal to " + uppercaseFolder.toString());
}
}
}
根据文件规定:
两条路径是否相等取决于文件系统实现。在某些情况下,路径的比较不考虑大小写,而其他路径则区分大小写
如何修复代码或JVM,使Path.equals
针对两个不同的文件夹返回false(按大小写不同)
路径::等于的JavaDoc声明: 两条路径是否相等取决于文件系统实现。在某些情况下,路径的比较不考虑大小写,而其他路径则区分大小写。此方法不访问文件系统,文件不需要存在。如果需要,该方法可用于检查两个路径是否定位同一文件
由于您的
路径
没有针对文件系统
进行测试,因此您应该使用路径::equals的JavaDoc声明:
两条路径是否相等取决于文件系统实现。在某些情况下,路径的比较不考虑大小写,而其他路径则区分大小写。此方法不访问文件系统,文件不需要存在。如果需要,该方法可用于检查两个路径是否定位同一文件
由于您的路径
没有针对文件系统
进行测试,因此您应该使用。对于NTFS中几乎所有其他位置,Path.equals都是正确的。但是,“LXSS”文件是使用普通Windows API以外的其他方法创建的(例如不指定OBJ_CASE_INSENSITIVE)
如果你试着在Windows中浏览“M”和“M”,你会注意到你只能进入其中一个,因为它们看起来有相同的内容。因此,不仅AppData的某些部分很难区分,而且如果没有一点魔力,有些部分完全无法访问。对于NTFS中几乎所有其他位置,Path.equals都是正确的。但是,“LXSS”文件是使用普通Windows API以外的其他方法创建的(例如不指定OBJ_CASE_INSENSITIVE)
如果你试着在Windows中浏览“M”和“M”,你会注意到你只能进入其中一个,因为它们看起来有相同的内容。因此,不仅AppData的某些部分很难区分,而且如果没有一点魔力,有些部分完全无法访问。EDIT:我弄乱了Collectors.toMap代码,但问题是,我已经从问题中删除了它。我只是尝试在Win10机器中创建两个同名、不同大小写的文件夹,但无论是在终端还是在探索者中,我都无法做到这一点。当尝试进行第二次创建时,我总是得到“已存在”编辑:我弄乱了Collectors.toMap代码,但问题是,我已经从问题中删除了它。我只是尝试在Win10机器中创建两个文件夹,名称相同,大小写不同,但无论是在终端还是在资源管理器中,我都无法做到这一点。当尝试进行第二次创建时,我总是得到“已经存在”抱歉,但这不是一个可行的解决方案,Files.isSameFile需要访问文件系统,问题的一部分在于路径被用作Map的键。在我的索引器代码中,对文件系统的所有必要调用都是通过索引过程执行的(即收集上次修改的日期,sha256散列),其余代码不假定它们有权访问文件系统。出现此问题的代码负责创建系统的可视化呈现。由于无法保证equals方法,您应该选择其他类型作为键,例如String。事实证明,Files::isSameFile不会返回所需的结果,它会返回true
,因为它实际上与Java的目录相同;使用JavaNIO浏览每个文件夹将显示相同的内容。只有Windows上Ubuntu上的WSL/Bash能够在两个不同的区分大小写的目录中导航。抱歉,这不是一个可行的解决方案,Files.isSameFile需要访问文件系统,部分问题在于路径被用作Map的键。在我的索引器代码中,对文件系统的所有必要调用都是通过索引过程执行的(即收集上次修改的日期,sha256散列),其余代码不假定它们有权访问文件系统。出现此问题的代码负责创建系统的可视化呈现。由于无法保证equals方法,您应该选择其他类型作为键,例如String。事实证明,Files::isSameFile不会返回所需的结果,它会返回true
,因为它实际上与Java的目录相同;使用JavaNIO浏览每个文件夹将显示
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public final class DuplicateFileIndexing {
public static void main(String[] args) throws IOException {
Path originFolder = Paths.get("C:\\Users\\Terminal\\AppData\\Local\\lxss\\rootfs\\usr\\share\\terminfo");
Path lowercaseFolder = originFolder.resolve("m");
Path uppercaseFolder = originFolder.resolve("M");
System.out.println(originFolder.toAbsolutePath().toString());
List<String> directoriesInOriginFolder = Files.walk(originFolder, 1)
.filter(path -> Files.isDirectory(path))
.map(path -> path.getFileName().toString())
.collect(Collectors.toList());
System.out.println(directoriesInOriginFolder);
if (directoriesInOriginFolder.contains("m")) {
System.out.println("Has a m folder");
}
if (directoriesInOriginFolder.contains("M")) {
System.out.println("Has a M folder");
}
System.out.println("---");
System.out.println("Files in 'm' folder");
Files.walk(lowercaseFolder, 1)
.map(path -> path.toAbsolutePath().toString())
.forEach(System.out::println);
System.out.println("---");
System.out.println("Files in 'M' folder");
Files.walk(uppercaseFolder, 1)
.map(path -> path.toAbsolutePath().toString())
.forEach(System.out::println);
System.out.println("---");
System.out.println("Parent of files in 'm' folder");
Files.walk(lowercaseFolder, 1)
.map(path -> path.toAbsolutePath().toString() + " is a child of " + path.getParent().toString())
.forEach(System.out::println);
System.out.println("---");
System.out.println("Parent of files in 'M' folder");
Files.walk(uppercaseFolder, 1)
.map(path -> path.toAbsolutePath().toString() + " is a child of " + path.getParent().toString())
.forEach(System.out::println);
System.out.println("---");
if (lowercaseFolder.equals(uppercaseFolder)) {
System.out.println(lowercaseFolder.toString() + " is equal to " + uppercaseFolder.toString());
}
}
}
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo
[terminfo, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, a, b, c, d, E, e, f, g, h, i, j, k, L, l, M, m, N, n, o, P, p, Q, q, r, s, t, u, v, w, X, x, z]
Has a m folder
Has a M folder
---
Files in 'm' folder
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\m
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\m\MtxOrb
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\m\MtxOrb162
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\m\MtxOrb204
---
Files in 'M' folder
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\M
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\M\MtxOrb
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\M\MtxOrb162
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\M\MtxOrb204
---
Parent of files in 'm' folder
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\m is a child of C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\m\MtxOrb is a child of C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\m
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\m\MtxOrb162 is a child of C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\m
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\m\MtxOrb204 is a child of C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\m
---
Parent of files in 'M' folder
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\M is a child of C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\M\MtxOrb is a child of C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\M
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\M\MtxOrb162 is a child of C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\M
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\M\MtxOrb204 is a child of C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\M
---
C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\m is equal to C:\Users\Terminal\AppData\Local\lxss\rootfs\usr\share\terminfo\M