我有一个scala应用程序,该应用程序处理来自的某些目录中的二进制文件resources
。我想得到这个目录,java.io.File
并列出所有内容。在最新的sbt中,我无法直接进行操作。
我已经为我的问题创建了最小的回购协议:
https://github.com/mat646/sbt-resource-bug
sbt 0.13.18及更低版本不会发生此问题。因此,经过一些研究,我发现自sbt 1.0起,设计已更改,并且此问题已在此处解决:
https://github.com/sbt/sbt/issues/3963
所以提供的解决方案是:
1.降级到sbt 0.13(我想避免)
2.提取项目jar本身(我发现这很麻烦,因为我还没有解决-https:// github。 COM / SBT / IO包含gunzip
的方法,但对我来说这仍然无法提取我从jar目录,但在这里,我可能误解了如何提取项目JAR嵌套文件)
(以便在SBT 1.0+作品上构建罐子读取文件getResourceAsStream
作品完美,但因我的问题而失败)
感谢您提供的帮助和解决方法!
run
任务似乎已在正向运行任务中重新连接到bgRun#3477,其副作用之一是在类路径而不是类目录上使用打包的jar,以便getClass.getResource("/my-dir")
返回
jar:file:/var/folders/84/hm7trc012j19rbgtn2h4fg6c0000gp/T/sbt_1397efb8/job-1/target/43a04671/sbt-resource-bug_2.12-0.1.jar!/my-dir
Run Code Online (Sandbox Code Playgroud)
代替
file:/Users/amani/IdeaProjects/sbt-resource-bug/target/scala-2.12/classes/my-dir
Run Code Online (Sandbox Code Playgroud)
run
为旧行为作为一种解决方法,我们可以尝试build.sbt
像这样恢复重新布线:
run := Defaults.runTask(fullClasspath in Runtime, mainClass in run in Compile, runner in run).evaluated
Run Code Online (Sandbox Code Playgroud)
现在File.listFiles
应该可以工作,例如,
new File(getClass.getResource("/my-dir").getFile).listFiles().foreach(println)
Run Code Online (Sandbox Code Playgroud)
应该输出
sbt:sbt-resource-bug> run
[info] Running Main
/Users/mario/IdeaProjects/sbt-resource-bug/target/scala-2.12/classes/my-dir/file2.txt
/Users/mario/IdeaProjects/sbt-resource-bug/target/scala-2.12/classes/my-dir/file1.txt
Run Code Online (Sandbox Code Playgroud)
JarFile
直接使用JAR或者,如果我们希望保持当前的连接状态,JarFile
可以用来列出JAR文件的内容。例如,给定
object ListFileNamesInJarDirectory {
def apply(dir: String): List[String] = {
import scala.collection.JavaConverters.enumerationAsScalaIteratorConverter
val jar = new File(getClass.getProtectionDomain().getCodeSource().getLocation().getPath())
(new JarFile(jar))
.entries()
.asScala
.toList
.filter(!_.isDirectory)
.filter(entry => entry.getRealName.contains(dir))
.map(_.getName)
}
}
Run Code Online (Sandbox Code Playgroud)
然后
ListFileNamesInJarDirectory("my-dir").foreach(println)
Run Code Online (Sandbox Code Playgroud)
应该输出
my-dir/file1.txt
my-dir/file2.txt
Run Code Online (Sandbox Code Playgroud)
之后,getResourceAsStream
可以用来获取jar中的实际文件。注意我们如何File
表示jar文件:
val jar = new File(getClass.getProtectionDomain().getCodeSource().getLocation().getPath())
Run Code Online (Sandbox Code Playgroud)