这似乎是一个经典问题,但我找不到任何关于它的事情" clojure方式"。
所以,我在资源/(leiningen项目)里面有一个foo /目录。当jar&#d; / uberjar' d时,这个foo /目录放在jar的根目录下。由于jar中的文件在运行时可能不是物理上一致的,因此您无法使用基本复制功能以递归方式将目录复制到外部世界。
存在Java世界的几种解决方案(例如How to write a Java program which can extract a JAR file and store its data in specified directory (location)?和How to extract directory (and sub directories) from jar resource?),但我没有找到任何现有的Clojure解决方案。 作为初学者(包括Clojure和Java),我不确定如何将上述解决方案转换为Clojure。逐字逐句地从Java翻译成Clojurish Java Interop看起来并不正确。 是否有"官方",clojure-idiomatic方式来做到这一点?
请注意,我使用的是Raynes' fs实用程序库。似乎没有直接这样做的功能,但是可能有一些我可以用来简化过程的元素? (除了明显的基本io糖)
答案 0 :(得分:4)
几个月前我写了cpath-clj,它将通过URI列出类路径上的资源。然后,您可以尝试以下操作:
(require '[cpath-clj.core :as cp]
'[clojure.java.io :as io])
(doseq [[path uris] (cp/resources (io/resource "foo"))
:let [uri (first uris)
relative-path (subs path 1)
output-file (io/file output-directory relative-path)]]
(with-open [in (io/input-stream uri)]
(io/copy in output-file)))
由于图书馆没有记住这个用例,因此有一些杂耍:
(cp/resources (io/resource "foo"))
将为您提供您的 foo
目录的内容 - 如果您只使用了(cp/resources "foo")
,则会在类路径中找到所有此类目录, path
,这就是函数返回多个uris
的原因;在我们的例子中,只有第一个是感兴趣的。path
总是以斜线开头,所以要获得相对的斜杠,我们必须将其删除。也许这对你有帮助。
答案 1 :(得分:0)
我不确定惯用部分,但资源目录中的文件可以这样列出
(defn list-resource
[resource-dir]
(let [resource (io/file (io/resource resource-dir))]
(file-seq resource)))
将文件从资源中的目录foo复制到当前路径就像
一样简单(io/copy (io/file (io/resource "foo/test.txt")) (io/file "test.txt"))
将这两者结合起来,您应该能够编写一个递归函数来完成您的要求
答案 2 :(得分:0)
在尝试了更多并从#clojure获得帮助之后,我能够想出一种"类似于clojurish-i-guess"从我之前的第一个链接翻译:
(ns my-ns
(:require [me.raynes.fs :as f])
(:import [java.util.jar JarFile JarEntry]))
(defn extract-dir-from-jar
"Takes the string path of a jar, a dir name inside that jar and a destination
dir, and copies the from dir to the to dir."
[^String jar-dir from to]
(let [jar (JarFile. jar-dir)]
(doseq [^JarEntry file (enumeration-seq (.entries jar))]
(if (.startsWith (.getName file) from)
(let [f (f/file to (.getName file))]
(if (.isDirectory file)
(f/mkdir f)
(do (f/mkdirs (f/parent f))
(with-open [is (.getInputStream jar file)
os (io/output-stream f)]
(io/copy is os)))))))))
我想我可以稍微整理一下(特别是在.startsWith位附近),但至少可以完美地运作。
答案 3 :(得分:0)
(defn copy-resource! [resource-filename]
(let [resource-file (io/resource resource-filename)
tmp-file (io/file "/tmp" resource-filename)]
(with-open [in (io/input-stream resource-file)] (io/copy in tmp-file))))
(copy-resource! "my-logo.png")