应用程序如何在 运行 时间遍历其中一个包的内容?
How can an app walk through the contents of one of its packages at run time?
此方法不适用:
Files.walk(Paths.get("folder name"))
因为当应用程序 运行 打包为 jar 时,它不包含文件对象。
有没有一种方法可以让应用程序在运行时遍历其中一个包的所有内容?
有;打开 jar 文件(使用 java.io.JarFile
)并浏览 entries()
返回的条目。如果您的 jar 是从其他地方流式传输的,还有 JarInputStream
。
但是,听起来您已经将 'jar file' 等同于 'my application, at runtime'。
这是一个棘手的举动。对于初学者来说,弄清楚你自己的 jar 是可能的,但有点 hacky,更重要的是,这意味着你的应用程序直接无法工作,除非它是 jar 形式。这使部署、开发和调试变得复杂。
没有必要这样做。
您可以向 java 索要来自 'whereever it is currently picking up class files' 的资源。 class 文件是对应用程序 运行 至关重要的资源。例如GUI 应用程序的图标文件。两者应该来自同一个地方,那是哪里?那是抽象的,你应该遵循抽象,这样 'load resource' 代码在调试时和在运行时一样好。
此系统是 MyClass.class.getResource("file.txt")
,它将在 MyClass.class
所在的同一位置查找 file.txt
,即使它在 jar 文件中、实时生成或从中获取某处数据库中的 BLOB 对象,或通过网络流式传输。
缺点是,这个系统没有列出文件的抽象。仅用于获取具有特定名称的资源。
SPI 系统是解决方案:制作一个列出(每行一个资源)资源的文件 - 而不是 'list dir',您 'parse each line of CONTENTS.txt' 用于等效操作。然后,如果需要,您可以使用注释处理器来自动创建和维护此内容文件。
ServiceLoader
内置于 JDK 本身,但它专门用于加载 class 文件而不是其他资源。但是原理很简单,手写5行代码左右就可以了。
您可以使用 Files / NIO 迭代任何 ZIP / JAR 文件的内容,但您需要访问 ZIP 文件系统。然后您可以调用 Files.find
或 Files.walk
对 ZIP / JAR 存档的内容。
例如,这将打印 jar 中每个路径的内容:
Path zip = Path.of("your.jar");
BiPredicate<Path, BasicFileAttributes> predicate = (p,a) -> true;
try (FileSystem fs = FileSystems.newFileSystem(zip)) {
for (Path root : fs.getRootDirectories()) {
try(Stream<Path> stream = Files.find(root, Integer.MAX_VALUE, predicate)) {
stream.forEach(System.out::println);
}
}
}
从 ZIP 文件系统获得 Path
对象后,您可以使用 NIO 文件调用以正常方式访问条目的内容,例如 Files.newInputStream
或 Files.copy
.
此方法不适用:
Files.walk(Paths.get("folder name"))
因为当应用程序 运行 打包为 jar 时,它不包含文件对象。
有没有一种方法可以让应用程序在运行时遍历其中一个包的所有内容?
有;打开 jar 文件(使用 java.io.JarFile
)并浏览 entries()
返回的条目。如果您的 jar 是从其他地方流式传输的,还有 JarInputStream
。
但是,听起来您已经将 'jar file' 等同于 'my application, at runtime'。
这是一个棘手的举动。对于初学者来说,弄清楚你自己的 jar 是可能的,但有点 hacky,更重要的是,这意味着你的应用程序直接无法工作,除非它是 jar 形式。这使部署、开发和调试变得复杂。
没有必要这样做。
您可以向 java 索要来自 'whereever it is currently picking up class files' 的资源。 class 文件是对应用程序 运行 至关重要的资源。例如GUI 应用程序的图标文件。两者应该来自同一个地方,那是哪里?那是抽象的,你应该遵循抽象,这样 'load resource' 代码在调试时和在运行时一样好。
此系统是 MyClass.class.getResource("file.txt")
,它将在 MyClass.class
所在的同一位置查找 file.txt
,即使它在 jar 文件中、实时生成或从中获取某处数据库中的 BLOB 对象,或通过网络流式传输。
缺点是,这个系统没有列出文件的抽象。仅用于获取具有特定名称的资源。
SPI 系统是解决方案:制作一个列出(每行一个资源)资源的文件 - 而不是 'list dir',您 'parse each line of CONTENTS.txt' 用于等效操作。然后,如果需要,您可以使用注释处理器来自动创建和维护此内容文件。
ServiceLoader
内置于 JDK 本身,但它专门用于加载 class 文件而不是其他资源。但是原理很简单,手写5行代码左右就可以了。
您可以使用 Files / NIO 迭代任何 ZIP / JAR 文件的内容,但您需要访问 ZIP 文件系统。然后您可以调用 Files.find
或 Files.walk
对 ZIP / JAR 存档的内容。
例如,这将打印 jar 中每个路径的内容:
Path zip = Path.of("your.jar");
BiPredicate<Path, BasicFileAttributes> predicate = (p,a) -> true;
try (FileSystem fs = FileSystems.newFileSystem(zip)) {
for (Path root : fs.getRootDirectories()) {
try(Stream<Path> stream = Files.find(root, Integer.MAX_VALUE, predicate)) {
stream.forEach(System.out::println);
}
}
}
从 ZIP 文件系统获得 Path
对象后,您可以使用 NIO 文件调用以正常方式访问条目的内容,例如 Files.newInputStream
或 Files.copy
.