Java 如何在 jar 环境中读取文件夹并列出该文件夹中的文件而不是 IDE
Java how to read folder and list files in that folder in jar environment instead of IDE
我的问题是我在 src 下创建了一个文件夹(名称是 IconResources),在 IconResources 中有很多图片。目录是这样的:
- 项目名称
- 来源
- 套餐 1
- 套餐 2
- IconResources(这是目标文件夹)
我想列出所有图片文件名并对这些图片做一些处理。而且我发现 File.list() 仅在 IDE 中有效,如果我将项目导出到 jar 以使其独立,则无法正常工作。于是搜索了一下,发现应该使用inputstream和outputstream。现在我发现 i/o 流可以很好地处理单个文件。但我想使用输入流和输出流来读取文件夹(IconResource),然后列出该文件夹中的文件。
所以我的问题是如何使用 i/o put stream 加载文件夹并迭代文件夹以列出该文件夹中的文件名。这些东西不仅应该在 IDE 下工作,而且应该在导出的 jar 下工作。
我的代码如下:
private void initalizeIconFiles(File projectDirectory){
URL a = editor.getClass().getResource("/IconResources/");// Get Folder URL
List<String> iconFileNames=new ArrayList<String>();//Create a list to store file names from IconResource Folder
File iconFolder = new File(a.getFile());
Path path=Paths.get(iconFolder.getPath());
DirectoryStream<Path> stream = Files.newDirectoryStream(path) ;
for (Path entry : stream) {
if (!Files.isDirectory(entry)) {
System.out.println(entry.getFileName().toString());
iconFileNames.add(entry.getFileName().toString());// add file name in to name list
}
}
}
以上代码只能在 运行 下 IDE 但在导出的 jar 中会崩溃。
您可以使用 JARInputStream
读取 JAR 文件的内容
这实际上是一个非常困难的问题,因为 ClassLoader
必须考虑到您可能在 另一个 文件夹 IconResources
运行时的类路径。
因此,无法 "official" 列出类路径中的整个文件夹。我在下面给出的解决方案是 a hack,目前可用于 URLClassLoader
的实现。这可能会发生变化。
如果你想要稳健的方法,你将需要使用类路径扫描器。其中有很多库形式,我个人最喜欢的是 Reflections,但是 Spring 内置了一个,还有很多其他选项。
开始破解。
通常,如果您 getResourceAsStream
在 URLClassLoader
上,那么它将 return 该文件夹中的资源流,每行一个。 URLClassLoader
是 JRE 使用的默认值,因此如果您不更改该行为,这种方法应该开箱即用。
假设我有一个具有以下类路径结构的项目:
/
text/
one.txt
two.txt
然后运行下面的代码:
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
try(
final InputStream is = loader.getResourceAsStream("text");
final InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
final BufferedReader br = new BufferedReader(isr)) {
br.lines().forEach(System.out::println);
}
将打印:
one.txt
two.txt
因此,为了获得该位置的 List<URL>
资源,您可以使用如下方法:
public static List<URL> getResources(final String path) throws IOException {
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
try (
final InputStream is = loader.getResourceAsStream(path);
final InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
final BufferedReader br = new BufferedReader(isr)) {
return br.lines()
.map(l -> path + "/" + l)
.map(r -> loader.getResource(r))
.collect(toList());
}
}
现在请记住,这些 URL
个位置 不透明 。它们不能被视为文件,因为它们可能位于 .jar
中,甚至可能位于 Internet 位置。因此,为了读取资源的内容,请在 URL
:
上使用适当的方法
final URL resource = ...
try(final InputStream is = resource.openStream()) {
//do stuff
}
我终于搞定了。我采用了 Boris the Spider 的答案,它在 IDE 中运行良好,但在导出的 Jar 中出现故障。然后我改
最终的 InputStream = loader.getResourceAsStream("text");
至
最终 InputStream = loader.getResourceAsStream("./text");
然后它在 IDE 和 JAR 中都有效。
我的问题是我在 src 下创建了一个文件夹(名称是 IconResources),在 IconResources 中有很多图片。目录是这样的:
- 项目名称
- 来源
- 套餐 1
- 套餐 2
- IconResources(这是目标文件夹)
- 来源
我想列出所有图片文件名并对这些图片做一些处理。而且我发现 File.list() 仅在 IDE 中有效,如果我将项目导出到 jar 以使其独立,则无法正常工作。于是搜索了一下,发现应该使用inputstream和outputstream。现在我发现 i/o 流可以很好地处理单个文件。但我想使用输入流和输出流来读取文件夹(IconResource),然后列出该文件夹中的文件。
所以我的问题是如何使用 i/o put stream 加载文件夹并迭代文件夹以列出该文件夹中的文件名。这些东西不仅应该在 IDE 下工作,而且应该在导出的 jar 下工作。 我的代码如下:
private void initalizeIconFiles(File projectDirectory){
URL a = editor.getClass().getResource("/IconResources/");// Get Folder URL
List<String> iconFileNames=new ArrayList<String>();//Create a list to store file names from IconResource Folder
File iconFolder = new File(a.getFile());
Path path=Paths.get(iconFolder.getPath());
DirectoryStream<Path> stream = Files.newDirectoryStream(path) ;
for (Path entry : stream) {
if (!Files.isDirectory(entry)) {
System.out.println(entry.getFileName().toString());
iconFileNames.add(entry.getFileName().toString());// add file name in to name list
}
}
}
以上代码只能在 运行 下 IDE 但在导出的 jar 中会崩溃。
您可以使用 JARInputStream
读取 JAR 文件的内容这实际上是一个非常困难的问题,因为 ClassLoader
必须考虑到您可能在 另一个 文件夹 IconResources
运行时的类路径。
因此,无法 "official" 列出类路径中的整个文件夹。我在下面给出的解决方案是 a hack,目前可用于 URLClassLoader
的实现。这可能会发生变化。
如果你想要稳健的方法,你将需要使用类路径扫描器。其中有很多库形式,我个人最喜欢的是 Reflections,但是 Spring 内置了一个,还有很多其他选项。
开始破解。
通常,如果您 getResourceAsStream
在 URLClassLoader
上,那么它将 return 该文件夹中的资源流,每行一个。 URLClassLoader
是 JRE 使用的默认值,因此如果您不更改该行为,这种方法应该开箱即用。
假设我有一个具有以下类路径结构的项目:
/
text/
one.txt
two.txt
然后运行下面的代码:
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
try(
final InputStream is = loader.getResourceAsStream("text");
final InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
final BufferedReader br = new BufferedReader(isr)) {
br.lines().forEach(System.out::println);
}
将打印:
one.txt
two.txt
因此,为了获得该位置的 List<URL>
资源,您可以使用如下方法:
public static List<URL> getResources(final String path) throws IOException {
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
try (
final InputStream is = loader.getResourceAsStream(path);
final InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
final BufferedReader br = new BufferedReader(isr)) {
return br.lines()
.map(l -> path + "/" + l)
.map(r -> loader.getResource(r))
.collect(toList());
}
}
现在请记住,这些 URL
个位置 不透明 。它们不能被视为文件,因为它们可能位于 .jar
中,甚至可能位于 Internet 位置。因此,为了读取资源的内容,请在 URL
:
final URL resource = ...
try(final InputStream is = resource.openStream()) {
//do stuff
}
我终于搞定了。我采用了 Boris the Spider 的答案,它在 IDE 中运行良好,但在导出的 Jar 中出现故障。然后我改
最终的 InputStream = loader.getResourceAsStream("text");
至
最终 InputStream = loader.getResourceAsStream("./text");
然后它在 IDE 和 JAR 中都有效。