Java NIO文件路径问题

56
我使用以下代码获取路径。
Path errorFilePath = FileSystems.getDefault().getPath(errorFile);

当我尝试使用File NIO移动文件时,我遇到以下错误:

java.nio.file.InvalidPathException: Illegal char <:> at index 2: \C:\Sample\sample.txt

我还尝试使用URL.encode(errorFile),但仍然出现相同的错误。


1
我想知道为什么我得到的前导字符是'/',而不是像问题中的''。我正在使用Windows 10,Java 8,Spring 3.2.14.RELEASE。 - jbarrameda
我们的问题出在这里:ClassLoader.getSystemResource("something").getPath() - 在Windows上,它会从file:/C:/mypath中删除file: - vikingsteve
8个回答

48

您需要将找到的资源转换为URI。它可以在所有平台上运行,并保护您免受路径可能出现的错误。您不必担心完整路径的样子,无论它是否以 '\' 或其他符号开头。如果您考虑这些细节-您正在做错事。

ClassLoader classloader = Thread.currentThread().getContextClassLoader();
String platformIndependentPath = Paths.get(classloader.getResource(errorFile).toURI()).toString();

4
这个答案比被接受的答案更好,因为有时候路径不是由你键入的,而是通过使用像ClassLoader.getResource()这样的东西获取的,在这种情况下,它会自动添加他在被接受的答案中提到的那个反斜杠符号! +1 - Joza100

38

路径\C:\Sample\sample.txt不能有前导\。应该只是C:\Sample\sample.txt


啊...我用来获取错误文件路径的代码添加了那个前导\。谢谢。 - Kathir
1
哇~,获取绝对路径时,开发者必须移除路径头部的“/”,这不是Windows操作系统或Path类中的一个bug吗? - 君主不是你
在Jenkins中执行时我遇到了同样的问题:java.nio.file.InvalidPathException: Illegal char <"> at index 0: "--tags at web.TestParallel.testParallel(TestParallel.java:23)第23行:Results results = Runner.parallel(getClass(), 5, "target/surefire-reports"); - Ashok kumar Ganesan

18

要使其适用于Windows和Linux/OS X,考虑执行以下操作:

String osAppropriatePath = System.getProperty( "os.name" ).contains( "indow" ) ? filePath.substring(1) : filePath;

如果您关心性能,建议将System.getProperty( "os.name" ).contains( "indow" )保存为常量,如下:

private static final boolean IS_WINDOWS = System.getProperty( "os.name" ).contains( "indow" );

然后使用:

String osAppropriatePath = IS_WINDOWS ? filePath.substring(1) : filePath;

@Eric,我的回答更通用于任何操作系统的特定行为。两者都很有价值。 - Sled

17

为确保在任何驱动器号上获得正确的路径,您可以执行以下操作:

path = path.replaceFirst("^/(.:/)", "$1");

这句话的意思是:如果字符串开头是一个斜线,然后跟着一个字符,冒号和另一个斜线,就用这个字符、冒号和斜线替换它(去掉开头的斜线)。

如果您使用的是Linux,路径中不应该出现冒号,也不会有匹配。如果您在Windows上运行,这应该适用于任何驱动器字母。


1
在 OP 中,前导字符是“\”,但我得到的是“/”字符,就像你的答案中一样,你有什么想法为什么会有这种差异? - jbarrameda
啊,发现得好。不,我不确定为什么会有差异。我个人看到的是“/”。所以,如果有人看到的是“\”,他们可以修改正则表达式来捕获“\”。 - Eric
1
可以获取环境路径分隔符,或者使用“^[/\\/](.:/)”字符类匹配任何一个斜杠。 - Raystorm

4

另一种消除前导分隔符的方法是创建一个新文件,将其转换为字符串,然后:

new File(Platform.getInstallLocation().getURL().getFile()).toString()

1

尝试像这样使用 C:\\Sample\\sample.txt

请注意双反斜杠。因为反斜杠是Java字符串转义字符,所以您必须键入两个反斜杠来表示一个“真正的”反斜杠。

或者

Java允许在任何平台上使用任一类型的斜杠,并进行适当的转换。这意味着您可以键入 C:/Sample/sample.txt 并在Windows上找到相同的文件。但是,我们仍然有路径“根目录”的问题。

处理多个平台上的文件的最简单解决方案是始终使用相对路径名。像 Sample/sample.txt 这样的文件名。


0

根据您使用路径对象的方式,您可能可以完全避免使用路径:

// works with normal files but on a deployed JAR gives "java.nio.file.InvalidPathException: Illegal char <:> "
URL urlIcon = MyGui.class.getResource("myIcon.png");
Path pathIcon = new File(urlIcon.getPath()).toPath();
byte bytesIcon[] = Files.readAllBytes(pathIcon);


// works with normal files and with files inside JAR:
InputStream in = MyGui.class.getClassLoader().getResourceAsStream("myIcon.png");
byte bytesIcon[] = new byte[5000];
in.read(bytesIcon);

0

普通的Windows环境

免责声明:我没有在普通的Windows环境下测试过这个。

"\\C:\\" 需要改为 "C:\\"

final Path errorFilePath = Paths.get(FileSystems.getDefault().getPath(errorFile).toString().replace("\\C:\\","C:\\"));

类Linux的Windows环境

我的Windows电脑有一个类Linux的环境,因此我必须将"/C:/"更改为"C:\\\\"

这段代码已在类Linux的Windows环境中测试通过:

final Path errorFilePath = Paths.get(FileSystems.getDefault().getPath(errorFile).toString().replace("/C:/","C:\\"));

1
这很好,但只有在文件在C驱动器上才能工作。请查看我的答案,以获得适用于任何驱动器字母的解决方案。 - Eric
“Linux-Like Windows”是什么意思?它是Windows的不同发行版,还是有任何配置可以启用它? - Bee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接