Idiomatic way to reference a bundled data file from Clojure source?

1,168 views
Skip to first unread message

stu

unread,
Jun 28, 2011, 9:12:33 PM6/28/11
to Clojure
Hi,

I'd like to bundle a collection of (JSON) datafiles with a Clojure
project source tree so that Clojure functions can reliably find and
open those datafiles.

What's the idiomatic way of going about this? In the past with other
languages I've used tricks like Ruby's ".dirname(__FILE__)/..."
construct but this kind of approach doesn't seem a good fit for
Clojure or for the JVM facilities it provides.

Can anyone point to a Clojure project that does this well?

Thanks,

Stu

Dave Ray

unread,
Jun 28, 2011, 9:59:46 PM6/28/11
to clo...@googlegroups.com
Hey,

I don't have a good example, but the right way to do is with resources
which are basically just files that live on the classpath:

* Put the files in a folder on your classpath. If your using
leiningen, the resources/ directory does this by default.
* Get a URL to the file with clojure.java.io/resource. If your file is
root/resources/my-project/my-resource.txt, you'd use (resource
"my-project/my-resource.txt").
* Read the contents of the file by passing the resource URL to
clojure.java.io/reader or one of its friends.

When you jar up your app the resource files will be included in the
jar and "just work".

Hope this helps.

Dave

> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

Stephen C. Gilardi

unread,
Jun 28, 2011, 10:17:35 PM6/28/11
to clo...@googlegroups.com
> I'd like to bundle a collection of (JSON) datafiles with a Clojure
> project source tree so that Clojure functions can reliably find and
> open those datafiles.
>
> What's the idiomatic way of going about this?

One idiomatic way to do this in Clojure is:

- store the files within a directory named resources at the top level of your project folder,
- arrange for that folder to be in your classpath at runtime,
- obtain a reference to the files at runtime using .getResource with a relative path.

If you use lieningen, the resources folder will be in your class path automatically and the files/directories it contains will be copied to the top level of your jar file if you make one.

Here's an example:

(defn resource [path]
(when path
(-> (Thread/currentThread) .getContextClassLoader (.getResource path))))

(require '[clojure.java.io :as io])
(slurp (io/file (resource "js/boo.js")))

I did this in a leiningen project called scratch. It returned the contents of the file

scratch/resources/js/boo.js

because scratch/resources was on the classpath.

See also http://alexott.net/en/clojure/ClojureLein.html .

--Steve

stu

unread,
Jun 29, 2011, 1:02:25 AM6/29/11
to Clojure
On Jun 29, 12:17 pm, "Stephen C. Gilardi" <squee...@mac.com> wrote:

> > I'd like to bundle a collection of (JSON) datafiles with a Clojure
> > project source tree so that Clojure functions can reliably find and
> > open those datafiles.
>
> > What's the idiomatic way of going about this?

Many thanks to Dave and Stephen for your answers--just what I
needed.

Stu

Shantanu Kumar

unread,
Jun 29, 2011, 12:50:20 PM6/29/11
to Clojure
The idiomatic way may be to include the file(s) in the classpath and
there is already a `resource` function in clojure.java.io that can
load it from the classpath:

$ lein new foo
$ cd foo
$ mkdir resources
$ cat>resources/test.txt
hello
world
foo
bar
^D
$ # edit src/foo/core.clj as follows
(ns foo.core
(:require [clojure.java.io :as jio]))

(println (slurp (jio/resource "test.txt")))

$ lein deps
$ lein repl
user=> (require 'foo.core)
hello
world
foo
bar
user=>

Regards,
Shantanu
Reply all
Reply to author
Forward
0 new messages