让我们有一个maven项目,其资源结构如下:
src/主/资源
虽然我找到了许多关于如何列出文件资源的答案,但我一直在寻找一种方法,如何列出资源中目录(或路径)的所有直接子目录,当应用程序同时从IDE(IntelliJ)和jar运行时,这种方法就行得通了。
目标是获取目录“di1”的子目录名称:subdi1, subdi2
我试过了
Thread.currentThread().getContextClassLoader().getResourceAsStream("dir1");
和使用返回的InputStream(包含子目录的名称),但不适用于jar。IntelliJ的作品。
我也试过用Spring框架但是
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("dir1/*");
无法在jar中正常工作-资源
数组为空。从IntelliJ工作。
我试图修改为
Resource[] resources = resolver.getResources("dir1/*/");
它可以从jar工作,但不能从IntelliJ工作。
当我从罐子开始工作时,我会以另一种方式打破它,反之亦然。我的最后一个想法是
Resource[] resources = resolver.getResources("dir1/**");
获取目录下的所有资源,然后只获取所需的资源。有没有更好的方法(最好不要太老套)?
似乎有以下工作:
public String[] getResourcesNames(String path) {
try {
URL url = getClassLoader().getResource(path);
if (url == null) {
return null;
}
URI uri = url.toURI();
if (uri.getScheme().equals("jar")) { // Run from jar
try (FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.emptyMap())){
Path resourcePath = fileSystem.getPath(path);
// Get all contents of a resource (skip resource itself), if entry is a directory remove trailing /
List<String> resourcesNames =
Files.walk(resourcePath, 1)
.skip(1)
.map(p -> {
String name = p.getFileName().toString();
if (name.endsWith("/")) {
name = name.substring(0, name.length() - 1);
}
return name;
})
.sorted()
.collect(Collectors.toList());
return resourcesNames.toArray(new String[resourcesNames.size()]);
}
} else { // Run from IDE
File resource = new File(uri);
return resource.list();
}
} catch (IOException | URISyntaxException e) {
return null;
}
}
private ClassLoader getClassLoader() {
return Thread.currentThread().getContextClassLoader();
}
jar的问题是,没有文件夹本身,只有条目,而文件夹只是名称中带有尾随斜杠的条目。这可能就是为什么返回jar中的文件夹,而不是从de IDE返回,其中文件夹名称不以/
结尾。出于类似的原因,请在IDE上工作,但不要在jar中工作,因为文件夹名称在jar中以斜杠结尾。
Spring基于文件处理资源,如果您尝试获取一个空文件夹作为资源,它将失败,而这个空文件夹通常不会添加到jar中。此外,查找文件夹也不太常见,因为内容在文件中,唯一有用的信息是它包含的文件。
实现这一点的最简单方法是使用dir1模式,因为这将列出所有文件以及dir1目录下包含文件的文件夹。
如果程序是从jar文件执行的,“检测”,也可以选择不同的策略列出文件夹,但这种解决方案甚至更“黑客”。
这里有一个使用第一个选项的示例,pattern
dir1/***
(以防万一):
String folderName = "dir1";
String folderPath = String.format("%s/**", folderName);
Resource[] resources = resolver.getResources(folderPath);
Map<String, Resource> resourceByURI = Arrays.stream(resources)
.collect(Collectors.toMap(resource -> {
try {
return resource.getURI().toString();
} catch (IOException e) {
throw new RuntimeException(e);
}
}, Function.identity()));
resourceByURI是包含由其URI标识的资源的映射。
Resource folder = resolver.getResource(folderName);
int folderLength = folder.getURI().toString().length();
Map<String, String> subdirectoryByName = resourceByURI.keySet().stream()
.filter(name -> name.length() > folderLength
&& name.indexOf("/", folderLength + 1) == name.length() - 1)
.collect(Collectors.toMap(Function.identity(), name -> name.substring(folderLength,
name.indexOf("/", folderLength + 1))));
然后,您可以获取文件夹的URI,计算路径的偏移量(类似于spring所做的),然后检查名称是否比当前文件夹长(在jar中丢弃相同的文件夹),以及名称是否最终包含一个单一的。最后收集到一个由URI再次标识的映射,其中包含文件夹的名称。文件夹名称的集合是子目录byname。values()
。
我最终得到了这个(使用Spring):
public class ResourceScanner {
private PathMatchingResourcePatternResolver resourcePatternResolver;
public ResourceScanner() {
this.resourcePatternResolver = new PathMatchingResourcePatternResolver();
}
public Resource getResource(String path) {
path = path.replace("\\", "/");
return resourcePatternResolver.getResource(path);
}
public Resource[] getResources(String path) throws IOException {
path = path.replace("\\", "/");
return resourcePatternResolver.getResources(path);
}
public Resource[] getResourcesIn(String path) throws IOException {
// Get root dir URI
Resource root = getResource(path);
String rootUri = root.getURI().toString();
// Search all resources under the root dir
path = (path.endsWith("/")) ? path + "**" : path + "/**";
// Filter only direct children
return Arrays.stream(getResources(path)).filter(resource -> {
try {
String uri = resource.getURI().toString();
boolean isChild = uri.length() > rootUri.length() && !uri.equals(rootUri + "/");
if (isChild) {
boolean isDirInside = uri.indexOf("/", rootUri.length() + 1) == uri.length() - 1;
boolean isFileInside = uri.indexOf("/", rootUri.length() + 1) == -1;
return isDirInside || isFileInside;
}
return false;
} catch (IOException e) {
return false;
}
}).toArray(Resource[]::new);
}
public String[] getResourcesNamesIn(String path) throws IOException {
// Get root dir URI
Resource root = getResource(path);
String rootUri = URLDecoder.decode(root.getURI().toString().endsWith("/") ? root.getURI().toString() : root.getURI().toString() + "/", "UTF-8");
// Get direct children names
return Arrays.stream(getResourcesIn(path)).map(resource -> {
try {
String uri = URLDecoder.decode(resource.getURI().toString(), "UTF-8");
boolean isFile = uri.indexOf("/", rootUri.length()) == -1;
if (isFile) {
return uri.substring(rootUri.length());
} else {
return uri.substring(rootUri.length(), uri.indexOf("/", rootUri.length() + 1));
}
} catch (IOException e) {
return null;
}
}).toArray(String[]::new);
}
}
源代码是一个Java Maven项目。 Java resources目录包含包含配置文件的子目录。配置文件可以作为维护过程添加和删除。不应知道的文件名。 我如何获得一个提到的项目“资源”目录中的所有文件的列表? 路径是“resources”目录中的文件夹名。
问题内容: 我正在尝试获取资源的途径,但是我没有运气。 这是可行的(在IDE和JAR中都可以),但是这样一来,我无法获取文件的路径,只能获取文件内容: 如果我这样做: 结果是: 有没有办法获取资源文件的路径? 问题答案: 这是故意的。“文件”的内容可能无法作为文件使用。请记住,您正在处理的类和资源可能是JAR文件或其他类型的资源的一部分。类加载器不必为资源提供文件句柄,例如jar文件可能尚未扩展为
问题内容: 我知道还有其他针对同一问题的问题,但问题是解决方案对我不起作用。我有一个小工具,它应该读取我想拥有的文件并将其打包为资源,并依赖于其他我希望将其作为jar而不是单个类的项目(我正在使用Eclipse Helios)。 作为Eclipse中的应用程序,我可以通过以下方式访问资源 当且仅当将资源文件夹放置在输出路径(已编译的源)下时,并且如果将其放置在src文件夹中时,则不是这样。 当我打
问题内容: 我想像这样从我的jar中读取资源: //Read the file 并且在Eclipse中运行它时效果很好,但是如果我将其导出到jar中运行,则会出现: 我真的不知道为什么,但是经过一些测试,我发现我是否改变了 至 然后它的作用相反(它在jar中起作用,但在Eclipse中不起作用)。 我正在使用Eclipse,并且包含我的文件的文件夹位于类文件夹中。 问题答案: 而不是尝试将资源作为
问题内容: 我有一个带有工具栏的Java项目,该工具栏上带有图标。这些图标存储在名为resources /的文件夹中,因此路径可能是“ resources / icon1.png”。该文件夹位于我的src目录中,因此在编译后,该文件夹将被复制到bin / 我正在使用以下代码访问资源。 (imageName将为“ resources / icon1.png”等)。在Eclipse中运行时,效果很好。
问题内容: 我需要读取代码中的文件。它实际上位于此处: 我将其放在源包中,以便在创建可运行的jar文件(导出-> Runnable JAR文件)时将其包含在jar中。最初,我将其放在项目根目录中(并尝试了一个普通的子文件夹),但导出文件并未将其包含在jar中。 如果在我的代码中,我这样做: jar文件正确地找到了该文件,但是在本地运行(运行方式-> Java Main应用程序)会引发文件未找到异常