在与Clojure中运行代码相同的目录中打开文件

Ula*_*men 11 clojure

我正在尝试用Clojure编写一些测试.其中一个测试涉及在与运行的测试文件相同的目录中打开一个html文件,以将内容用作测试输入(Python中广泛使用的习语).我认为*file*var会完成这项工作,但事实并非如此,因为它是相对的.

假设我的项目使用默认的leiningen布局demoproj.我的测试就在那里~/projects/demoproj/test.这个目录再次复制了项目命名空间,我不是很喜欢它,但不管怎样.所以测试core.clj是在~/projects/demoproj/test/demoproj/test/core.clj.我也有一个small_page.html在同一目录中调用的文件.如果我把以下内容放入test/core.clj:

(println (-> (java.io.File. *file*)
             .getPath))
Run Code Online (Sandbox Code Playgroud)

这是我得到的:

demoproj/test/readibility.clj
Run Code Online (Sandbox Code Playgroud)

test与项目库的目录有关.我尝试仅使用此相对路径读取示例html页面,如下所示:

(slurp (-> (java.io.File. *file*)
            .getParent
            (java.io.File. "small_page.html")
            .getPath))
Run Code Online (Sandbox Code Playgroud)

这会导致IO错误,因为无法在该位置读取文件.我的下一个想法是获取当前工作目录并将其与相对路径连接.以下是我获取工作目录的方法:

(println (-> (java.io.File. ".")
             .getCanonicalPath))
Run Code Online (Sandbox Code Playgroud)

返回绝对路径:

/Path-to-home/projects/demoproj
Run Code Online (Sandbox Code Playgroud)

不好的是,这两个没有加入到文件的正确路径; test两者之间缺少一个组件.因此,加入这两个路径会导致不正确的目录路径.

所以,我的问题是,是否有一种可靠的方法来获取当前执行的代码文件的绝对路径?如果这是不可能的,那么这个成语的替代方案是什么,即如何解析相对于测试文件的位置的文件?

noi*_*ith 17

因为clojure代码和相关资源最终可以放在jar中,并且您希望代码能够运行,即使您访问的文件最终可能是jar的一部分而不是真正的文件系统,所以可靠的方法是使用io/resource,并确保有问题的文件位于资源路径中.

例如,我将以下内容作为当前项目中目录结构的一部分:

|-- project.clj
|-- resources
|   |-- caribou.properties
|   |-- config
|   |   |-- boot.clj
|   |   |-- development.clj
|   |   |-- local-dumped.clj
|   |   |-- local.clj
|   |   |-- production.clj
|   |   |-- staging.clj
|   |   `-- test.clj
|   `-- logging.properties
Run Code Online (Sandbox Code Playgroud)

我的project.clj中有以下内容:

  :resource-paths ["shared" "resources"]
Run Code Online (Sandbox Code Playgroud)

然后我可以在我的repl中执行以下操作:

user> (do (require '[clojure.java.io :as io]) (io/resource "config/boot.clj"))
#<URL file:/Users/me/this-project/resources/config/boot.clj>
user> (slurp *1)
"(use '[caribou.config :only (read-config configure environment)])\n(require '[clojure.java.io :as io])\n..."
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,io/resource返回一个URL,然后我可以将其传递给我要求的文件(在配置的资源路径中查找路径片段).如果将整个应用程序包装到uberjar中进行部署,则此代码仍然有效,而在这种情况下,创建io /文件并调用getParent会失败.