Clojure I/O Cookbook

There are a number of ways for us to read a file. If the file is small enough and can be held in memory, simplest approach is to use slurp which will return a string containing the content of the file,

(slurp "some.txt" )

For files that you can't or don't want to hold in memory, we can use BufferedReader, line-seq combo and process files on a line by line basis,

( with-open [rdr (java.io.BufferedReader. (java.io.FileReader. "project.clj" ))] ( let [seq (line-seq rdr)] (count seq)))

These days it is more common (at least for me) to retrieve a URL then it is to read file,

( defn fetch-url [address] ( with-open [stream (.openStream (java.net.URL. address))] ( let [buf (java.io.BufferedReader. (java.io.InputStreamReader. stream))] (apply str (line-seq buf))))) (fetch-url "http://google.com" )

Above will work on text files but corrupt binary files because BufferedReader assumes it is dealing with textual data, for downloading a binary file (video, music etc.) and saving it to a file on disk,

( defn fetch-data [url] ( let [con ( -> url java.net.URL. .openConnection) fields (reduce ( fn [h v] (assoc h (.getKey v) (into [] (.getValue v)))) {} (.getHeaderFields con)) size (first (fields "Content-Length" )) in (java.io.BufferedInputStream. (.getInputStream con)) out (java.io.BufferedOutputStream. (java.io.FileOutputStream. "out.file" )) buffer (make-array Byte /TYPE 1024)] ( loop [g (.read in buffer) r 0] ( if-not (= g -1) ( do (println r "/" size) (.write out buffer 0 g) ( recur (.read in buffer) (+ r g))))) (.close in) (.close out) (.disconnect con))) (fetch-data "http://google.com" )

Or if you prefer interacting with the socket directly,

( defn socket [host port] ( let [socket (java.net.Socket. host port) in (java.io.BufferedReader. (java.io.InputStreamReader. (.getInputStream socket))) out (java.io.PrintWriter. (.getOutputStream socket))] { :in in :out out})) ( def conn (socket "irc.freenode.net" 6667)) (println (.readLine ( :in conn)))

Now for writing stuff back to disk,

(spit "output.txt" "test" )

or bind out to a FileWriter and print the content,