Reading Files in Clojure

Reading and writing files are basic tasks needed for many Clojure programs. First we’ll look at some examples of reading files.

(ns reading-files
  (:require [clojure.java.io :as io]))

;; Reading files requires checking most calls for errors.
;; This helper will streamline our error checks below.
(defn check [result]
  (when (instance? Exception result)
    (throw result)))

(defn main []
  ;; Perhaps the most basic file reading task is
  ;; slurping a file's entire contents into memory.
  (let [dat (slurp "/tmp/dat")]
    (print dat))

  ;; You'll often want more control over how and what
  ;; parts of a file are read. For these tasks, start
  ;; by opening a file to obtain a reader.
  (with-open [rdr (io/reader "/tmp/dat")]
    ;; Read some bytes from the beginning of the file.
    ;; Allow up to 5 to be read but also note how many
    ;; actually were read.
    (let [b1 (char-array 5)
          n1 (.read rdr b1)]
      (printf "%d bytes: %s\n" n1 (String. b1 0 n1)))

    ;; You can also seek to a known location in the file
    ;; and read from there. In Clojure, we can use the Java
    ;; RandomAccessFile for this purpose.
    (with-open [raf (java.io.RandomAccessFile. "/tmp/dat" "r")]
      (.seek raf 6)
      (let [b2 (byte-array 2)
            n2 (.read raf b2)]
        (printf "%d bytes @ %d: %s\n" n2 6 (String. b2 0 n2))))

    ;; The io library provides some functions that may
    ;; be helpful for file reading. For example, we can
    ;; use line-seq to read lines from a file.
    (doseq [line (take 2 (line-seq rdr))]
      (println line)))

  ;; There is no built-in rewind, but we can
  ;; simply open the file again to start from the beginning.
  (with-open [rdr (io/reader "/tmp/dat")]
    ;; The clojure.java.io namespace provides a buffered
    ;; reader that may be useful both for its efficiency
    ;; with many small reads and because of the additional
    ;; reading methods it provides.
    (let [b4 (.readLine rdr)]
      (printf "First line: %s\n" b4))))

(main)

To run the program:

$ echo "hello" > /tmp/dat
$ echo "clojure" >>   /tmp/dat
$ clj reading-files.clj
hello
clojure
5 bytes: hello
2 bytes @ 6: cl
hello
clojure
First line: hello

In this Clojure version:

  1. We use slurp to read the entire file contents.
  2. For more controlled reading, we use clojure.java.io/reader.
  3. For seeking to specific positions, we use Java’s RandomAccessFile.
  4. We demonstrate line-by-line reading using line-seq.
  5. The with-open macro is used to ensure proper resource management.

Note that Clojure, being a JVM language, leverages Java’s IO capabilities. This allows for more direct file manipulation when needed, as shown with the RandomAccessFile example.

Next, we’ll look at writing files.

查看推荐产品

Comments powered by Disqus