Working with Files and Directories in Clojure
This cookbook covers working with files and directories from Clojure,
using functions in the clojure.java.io
namespace as well as parts of
the JDK via interoperability.
This work is licensed under a Creative Commons Attribution 3.0 Unported License (including images & stylesheets). The source is available on Github.
Preliminaries
Note that for the examples below, "io" is an alias for
clojure.java.io
. That is, it's assumed your ns
macro contains:
(:require [clojure.java.io :as io])
or else in the repl you've loaded it:
(require '[clojure.java.io :as io])
Recipes
Read a file into one long string
(def a-long-string (slurp "foo.txt"))
Note, you can pass urls to slurp
as well. See also slurp at
Clojuredocs.
Read a file one line at a time
Suppose you'd like to call my-func
on every line in a file,
and return the resulting sequence:
(with-open [rdr (io/reader "foo.txt")]
(mapv my-func (line-seq rdr)))
Note: mapv
is eager and returns a vector. If you use map
here, the reader
will be closed before the whole sequence is realized so you would need to
wrap the call to map
in a call to doall
anyway. The lines that
line-seq
gives you have no trailing newlines (and empty lines in the
file will yield empty strings (""
)).
Write a long string out to a new file
(spit "foo.txt"
"A long
multi-line string.
Bye.")
Overwrites the file if it already exists. To append, use
(spit "foo.txt" "file content" :append true)
Write a file one line at a time
Although you could do this by calling spit
with :append true
for
each line, that would be inefficient (opening the file for appending
for each call). Instead, use with-open
to keep a file open while
writing each line to it:
(with-open [wrtr (io/writer "foo.txt")]
(doseq [i my-vec]
(.write wrtr (str i "\n"))))
Check if a file exists
(.exists (io/file "filename.txt"))
Is it a directory? :
(.isDirectory (io/file "path/to/something"))
An io/file
is a java.io.File
object (a file or a directory). You can
call a number of functions on it, including:
exists Does the file exist?
isDirectory Is the File object a directory?
getName The basename of the file.
getParent The dirname of the file.
getPath Filename with directory.
mkdir Create this directory on disk.
To read about more available methods, see the java.io.File
docs.
Get a list of the files and dirs in a given directory
As File
objects:
(.listFiles (io/file "path/to/some-dir"))
Same, but just the names (strings), not File objects:
(.list (io/file "path/to/some-dir"))
The results of those calls are seqable.
See also
- https://github.com/clj-commons/fs
- the I/O section of the cheatsheet