从外部Clojar导入/使用资源 [英] Importing/using a resource from an external clojar

查看:137
本文介绍了从外部Clojar导入/使用资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想做的是将一个大文件(MIDI声音字体)打包在一个独立的Maven存储库/clojar中,然后能够以编程方式将其下拉并从单独的项目中使用它.事实证明,这项看似简单的任务比我预期的要复杂.

What I'm trying to do is package a large file (a MIDI soundfont) in a standalone Maven repo/clojar, and then be able to pull it down programmatically and use it from a separate project. This seemingly simple task is proving to be more complicated than I expected.

理想的情况是,如果有一种方法可以直接访问这些资源,或将它们公开为公共变量或其他内容.这是我尝试的第一件事-我做了这样的事情:

What would be ideal is if there were a way to access these resources directly, or expose them as public vars, or something. This is the first thing I tried -- I did something like this:

(ns midi.soundfont.fluid-r3
  (:require [clojure.java.io :as io]))

(def sf2
  (io/file (io/resource "fluid-r3.sf2")))

但是,我遇到的问题是io/resource仅在当前类路径上找到资源文件.一旦我尝试从另一个项目(或REPL)中要求此名称空间,我就会得到:

However, the problem that I'm running into is that io/resource only finds resource files on the current class path. As soon as I try to require this namespace from another project (or from the REPL), I get:

java.lang.IllegalArgumentException: Not a file: jar:file:/Users/dave/.m2/repository/midi/soundfont/fluid-r3/midi.soundfont.fluid-r3/0.1.0/midi.soundfont.fluid-r3-0.1.0.jar!/fluid-r3.sf2

如果不可能直接访问该资源,我将对涉及将文件复制到文件系统中某个路径的解决方案感到满意.我也确实尝试过此方法,但是在尝试从其他项目运行将文件复制到文件系统"方法时遇到了相同的问题-io/resource仍然无法找到文件,因为它不在当前类路径中

If it's not possible to access the resource directly, I would be happy with a solution that involves copying the file to some path in the filesystem. I did try this as well, but I ran into the same problem when trying to run the "copy the file to the filesystem" method from a different project -- io/resource still failed to locate the file because it's not on the current classpath.

我发现了以前在SO上曾问过的类似问题,例如:

I have found similar questions that have been asked on SO previously, such as:

  • Idiomatic Clojure to copy resources from running jar to outside
  • How to copy file inside jar to outside the jar?

但是,这些解决方案似乎仅与复制作为 current (运行)项目中的资源的文件有关.

However these solutions only seem to pertain to copying a file that is a resource in the current (running) project.

是否可以做这两件事之一?

Is it possible to do one of these two things?

  1. 从外部clojar访问资源文件
  2. 将资源文件导入到当前项目中,以便可以使用io/resource
  3. 进行访问
  1. Access a resource file from an external clojar
  2. Import the resource file into the current project, so that I can access it using io/resource

推荐答案

正如dbasch正确解释的那样,io/resource返回URL,而不是文件.但是为什么您可以通过以下方式打开该网址 是在REPL上是io/file,还是在罐子中不是lein run?这是因为在第一种情况下,URL指向纯文件 在文件系统中,而与jar一起运行时的URL指向jar内的资源,因此它不是正确的文件.

As dbasch correctly explained, io/resource returns a URL, not a file. But why you are being able to open that URL with io/file on the REPL or lein run but not from the jar? That's because the URL in the first case points to the plain file in the filesystem, while the URL when running with the jar points to the resource inside the jar, so it's not a proper file.

我在此github存储库中做了一个示例.我将在此处复制-main代码以供参考:

I made an example in this github repo. I'll copy the -main code here for reference:

(defn -main [& args]
  (let [r (io/resource "greet")]
    (println r)
    (println (slurp r))
    (with-open [rdr (io/reader r)]
      (println (clojure.string/join ", " (line-seq rdr))))
    (println (io/file r))))

运行lein run显示:

› lein run
#<URL file:/home/nicolas/projects/clojure/resources/resources/greet>
hello
world

hello, world
#<File /home/nicolas/projects/clojure/resources/resources/greet>

运行uberjar显示:

Running the uberjar shows:

› java -jar target/resources-0.1.0-SNAPSHOT-standalone.jar 
#<URL jar:file:/home/nicolas/projects/clojure/resources/target/resources-0.1.0-SNAPSHOT-standalone.jar!/greet>
hello
world

hello, world
Exception in thread "main" java.lang.IllegalArgumentException: Not a file: jar:file:/home/nicolas/projects/clojure/resources/target/resources-0.1.0-SNAPSHOT-standalone.jar!/greet
        at clojure.java.io$fn__8588.invoke(io.clj:63)
        at clojure.java.io$fn__8572$G__8556__8577.invoke(io.clj:35)

查看#<URL file:/home/nico...#<URL jar:file:/home/nico...之间的区别,这说明了为什么无法在其上调用(io/file)的原因,但是可以使用slurp进行阅读或使用io/reader创建阅读器.

See the difference between #<URL file:/home/nico... and #<URL jar:file:/home/nico..., that explains why you can't call (io/file) on it, but you can read it with slurp or create a reader with io/reader.

这篇关于从外部Clojar导入/使用资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆