当路径包含任何空格(例如%20)时,在Java ist中加载文件不起作用

当路径包含任何空格(例如%20)时,在Java ist中加载文件不起作用,java,junit,whitespace,java-io,junit5,Java,Junit,Whitespace,Java Io,Junit5,我回顾了很多关于Java文件和路径问题的答案,甚至有些答案在路径中带有空格,但没有回答我想问的问题: 在非空白目录中,为什么下面的代码可以工作?否则为什么会失败 我把我的问题简单地说成是问题的本质,所以我希望任何人都能向我解释这个问题;-) 我有一个旧的API,我必须提供一些图像的文件句柄,我决定通过相对路径URL方法加载图像 我知道这在jar中不起作用,但我还不打算从jar中加载任何图像。该解决方案足以满足我当前的需求 我现在不想把一切都变成溪流 但是任何执行的成功与否在很大程度上取决于它所处

我回顾了很多关于Java文件和路径问题的答案,甚至有些答案在路径中带有空格,但没有回答我想问的问题:

在非空白目录中,为什么下面的代码可以工作?否则为什么会失败

我把我的问题简单地说成是问题的本质,所以我希望任何人都能向我解释这个问题;-)

我有一个旧的API,我必须提供一些图像的文件句柄,我决定通过相对路径URL方法加载图像

我知道这在jar中不起作用,但我还不打算从jar中加载任何图像。该解决方案足以满足我当前的需求 我现在不想把一切都变成溪流

但是任何执行的成功与否在很大程度上取决于它所处的目录!这对我来说似乎很奇怪

因此,我编写了一个JUnit测试,并提供了测试资源目录中的一些文件来研究这个问题

└───imageload    
    ├───src
    │   ├───main
    │   │   ├───java
    │   │   └───resources
    │   └───test
    │       ├───java
    │       │   └───stupid
    │       │       └───test
    │       └───resources
    │           └───testset
    └───target
        ├───generated-test-sources
        │   └───test-annotations
        └───test-classes
            ├───stupid
            │   └───test
            └───testset

这是使问题变得明显的测试代码:

package.test;
[…省略进口…]
公共类SimpleTest{
公共静态最终文件getFileByRelativePathURL(字符串相对路径){
URL URL=Thread.currentThread().getContextClassLoader().getResource(relativePath);
File File=新文件(url.getPath());
返回文件;
}
@试验
void loadImage(){
File theFile=SimpleTest.getFileByRelativePathURL(“testset/black.jpg”);
Boolean exists=theFile.exists();
资产真实(存在);
}
}
在该目录下运行测试时,所有操作都正常:

  • D:\Temp\working\imageload\
从此处运行时失败:

  • D:\Temp\not working\imageload\
我仔细查看了生成的文件实例,目录中的空间正确转义到该文件对象路径:

file = D:\Temp\not%20working\imageload\target\test-classes\testset\black.jpg
但%20肯定有问题,因为根据file类的“exists()”方法找不到该文件

我希望这个问题对你们中的许多人来说可能是显而易见的,但我仍然希望“theFile.exists()”在任何带或不带空格的目录中都返回true

我做错了什么

更新:有人问我的问题是否与本文重复:

不幸的是,这个解决方案并没有满足我寻找正确的相对路径的冲动。相反,它将绝对路径传递给文件构造函数

但是与JB Nizet的评论相结合帮助我理解了这个问题。。。虽然这是一个相当肮脏的解决方案,但我将我的相对URL方法更改为:

公共静态最终文件getFileByRelativePathURL(字符串相对路径){
URL URL=Thread.currentThread().getContextClassLoader().getResource(relativePath);
File File=new文件(url.getPath().replaceAll(“%20”和“);
返回文件;
}
现在一切都好了。。。愚蠢的我!
我真的必须用另一种方式来做;-)

多亏了JB Nizet的评论,我找到了一个解决方案,它可能更像是一个“肮脏的黑客”,而不是一个适当的解决方法,但它是解决我当前问题的有效方法

最初的错误是我假设可以使用转义URL路径作为文件路径,这显然是不正确的。因此,我通过修改相对路径方法删除了空格转义,如下所示:

公共静态最终文件getFileByRelativePathURL(字符串相对路径){
URL URL=Thread.currentThread().getContextClassLoader().getResource(relativePath);
File File=new文件(url.getPath().replaceAll(“%20”和“);
返回文件;
}
这使得“%20”替换中有了真正的空格,现在JUnit测试可以在所有包含空格的路径中工作。不过,对于其他空格或转义特殊字符,它不是一个解决方案

我将接受建议,并尽可能地解决旧API中文件对象的必要性


在我的代码中,我绝对支持流!:)

停止将类路径资源URL视为文件路径。做正确的事情,它就会很好地工作。返回一个URL或一个InputStream,而不是一个文件。这是一个很好的观点,但由于我尝试用文件提供的API不喜欢流,我如何避免这个问题?我知道这些问题看起来很愚蠢,但这正是我想要解决的…如果API需要文件只是为了能够从中读取,那么它的设计很糟糕,应该使用InputStream作为参数。您应该修复(或请求修复)API。如果API需要向其写入文件,则不应使用类路径资源向API提供数据,而应使用文件系统上的实际文件。如果您想要一个包含默认内容的文件,则可以在输入API之前将资源复制到文件中。这是一个很好的建议!我明白我能做什么了!至少我会尝试在我自己的代码中使用流!非常感谢你的帮助!:)我认为将你的“更新”作为答案是有意义的