I have a Scala application which processes binary files from some directory in resources. I would like to get this directory as java.io.File and li
run task seems to have been rewired in Forward run task to bgRun #3477 and one side-effect was to use packaged jars on classpaths instead of class directories, so that getClass.getResource("/my-dir") returns
jar:file:/var/folders/84/hm7trc012j19rbgtn2h4fg6c0000gp/T/sbt_1397efb8/job-1/target/43a04671/sbt-resource-bug_2.12-0.1.jar!/my-dir
instead of
file:/Users/amani/IdeaProjects/sbt-resource-bug/target/scala-2.12/classes/my-dir
run to the old behaviourAs a workaround, we could try reverting the rewiring in our build.sbt like so:
run := Defaults.runTask(fullClasspath in Runtime, mainClass in run in Compile, runner in run).evaluated
Now File.listFiles should work, for example,
new File(getClass.getResource("/my-dir").getFile).listFiles().foreach(println)
should output
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
JarFile to work with JARs directlyAlternatively, if we wish to keep the current rewiring, JarFile can be used to list the contents of JAR files. For example, given
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)
}
}
then
ListFileNamesInJarDirectory("my-dir").foreach(println)
should output
my-dir/file1.txt
my-dir/file2.txt
Afterwards, getResourceAsStream can be used to get at the actual files in the jar. Note how we get File to represent the jar file:
val jar = new File(getClass.getProtectionDomain().getCodeSource().getLocation().getPath())