मैं क्लोजर 1.3 में एक फाइल को पढ़ने और लिखने के "अनुशंसित" तरीके को जानना चाहता हूं।
- पूरी फाइल को कैसे पढ़ें
- फ़ाइल लाइन को लाइन से कैसे पढ़ें
- नई फाइल कैसे लिखें
- किसी मौजूदा फ़ाइल में एक पंक्ति कैसे जोड़ें
मैं क्लोजर 1.3 में एक फाइल को पढ़ने और लिखने के "अनुशंसित" तरीके को जानना चाहता हूं।
जवाबों:
यह मानते हुए कि हम केवल पाठ फ़ाइलें यहाँ कर रहे हैं और कुछ पागल बाइनरी सामान नहीं।
नंबर 1: मेमोरी में पूरी फाइल कैसे पढ़ें।
(slurp "/tmp/test.txt")
अनुशंसित नहीं जब यह वास्तव में बड़ी फ़ाइल है।
नंबर 2: फाइल लाइन को लाइन से कैसे पढ़ें।
(use 'clojure.java.io)
(with-open [rdr (reader "/tmp/test.txt")]
(doseq [line (line-seq rdr)]
(println line)))
with-open
मैक्रो ख्याल रखता है कि पाठक शरीर के अंत में बंद कर दिया है। रीडर फ़ंक्शन एक स्ट्रिंग (यह एक URL आदि भी कर सकता है) को एक में समेटता है BufferedReader
। line-seq
एक आलसी seq बचाता है। आलसी seq के अगले तत्व की मांग करने से पाठक से पढ़ी जाने वाली एक पंक्ति में परिणाम होता है।
ध्यान दें कि क्लोजर 1.7 से आगे, आप पाठ फ़ाइलों को पढ़ने के लिए ट्रांसड्यूसर का भी उपयोग कर सकते हैं ।
नंबर 3: नई फाइल में कैसे लिखें।
(use 'clojure.java.io)
(with-open [wrtr (writer "/tmp/test.txt")]
(.write wrtr "Line to be written"))
फिर, with-open
ध्यान रखता है कि BufferedWriter
शरीर के अंत में बंद हो। लेखक एक स्ट्रिंग को एक में जोड़ता है BufferedWriter
, जिसे आप जावा इंटरॉप के माध्यम से उपयोग करते हैं:(.write wrtr "something").
आप इसका उपयोग भी कर सकते हैं spit
, इसके विपरीत slurp
:
(spit "/tmp/test.txt" "Line to be written")
नंबर 4: एक मौजूदा फाइल के लिए एक लाइन संलग्न।
(use 'clojure.java.io)
(with-open [wrtr (writer "/tmp/test.txt" :append true)]
(.write wrtr "Line to be appended"))
ऊपर के समान, लेकिन अब एपेंड विकल्प के साथ।
या फिर spit
, इसके विपरीत slurp
:
(spit "/tmp/test.txt" "Line to be written" :append true)
पुनश्च: इस तथ्य के बारे में अधिक स्पष्ट होने के लिए कि आप एक फ़ाइल में पढ़ रहे हैं और लिख रहे हैं, और कुछ और नहीं, आप पहले एक फ़ाइल ऑब्जेक्ट बना सकते हैं और फिर इसे एक BufferedReader
राइटर में जमा कर सकते हैं:
(reader (file "/tmp/test.txt"))
;; or
(writer (file "tmp/test.txt"))
फ़ाइल फ़ंक्शन clojure.java.io में भी है।
PS2: कभी-कभी यह देखना आसान होता है कि वर्तमान निर्देशिका क्या है (इसलिए "")। आप दो तरीकों से संपूर्ण मार्ग प्राप्त कर सकते हैं:
(System/getProperty "user.dir")
या
(-> (java.io.File. ".") .getAbsolutePath)
(with-open [rdr (reader "/tmp/test.txt")] (line-seq rdr))
पैदावार IOException Stream closed
। क्या करें? हालांकि @satyagraha द्वारा जवाब के साथ अच्छे परिणाम मिल रहे हैं।
(with-open [rdr (reader "/tmp/test.txt")] (doall (line-seq rdr)))
doseq
रिटर्न nil
जो दु: ख-वापसी-मूल्य समय की ओर ले जा सकता है।
यदि फ़ाइल मेमोरी में फिट हो जाती है, तो आप इसे स्लरप और थूक के साथ पढ़ और लिख सकते हैं:
(def s (slurp "filename.txt"))
(अब एक स्ट्रिंग के रूप में एक फ़ाइल की सामग्री शामिल है)
(spit "newfile.txt" s)
यदि यह बाहर नहीं निकलता है और फ़ाइल सामग्री लिखता है तो यह newfile.txt बनाता है। यदि आप उस फ़ाइल को अपेंड करना चाहते हैं जो आप कर सकते हैं
(spit "filename.txt" s :append true)
एक फ़ाइल को पढ़ने या लिखने के लिए आप जावा के पाठक और लेखक का उपयोग करेंगे। वे नाम स्थान में लिपटे हैं clojure.java.io:
(ns file.test
(:require [clojure.java.io :as io]))
(let [wrtr (io/writer "test.txt")]
(.write wrtr "hello, world!\n")
(.close wrtr))
(let [wrtr (io/writer "test.txt" :append true)]
(.write wrtr "hello again!")
(.close wrtr))
(let [rdr (io/reader "test.txt")]
(println (.readLine rdr))
(println (.readLine rdr)))
; "hello, world!"
; "hello again!"
ध्यान दें कि स्लप / थूक और पाठक / लेखक के उदाहरणों के बीच अंतर यह है कि फ़ाइल बाद में खुली रहती है (लेट स्टेटमेंट में) और पढ़ना और लिखना बफ़र किया जाता है, इस प्रकार फ़ाइल से बार-बार पढ़ने / लिखने पर अधिक कुशल होता है।
यहाँ अधिक जानकारी है: slurp थूक clojure.java.io जावा के बफ़ररेडर जावा के लेखक
प्रश्न 2 के बारे में, कभी-कभी यह चाहता है कि लाइनों की धारा प्रथम श्रेणी की वस्तु के रूप में वापस आए। इसे एक आलसी अनुक्रम के रूप में प्राप्त करने के लिए, और अभी भी फ़ाइल ईओएफ पर स्वचालित रूप से बंद है, मैंने इस फ़ंक्शन का उपयोग किया है:
(use 'clojure.java.io)
(defn read-lines [filename]
(let [rdr (reader filename)]
(defn read-next-line []
(if-let [line (.readLine rdr)]
(cons line (lazy-seq (read-next-line)))
(.close rdr)))
(lazy-seq (read-next-line)))
)
(defn echo-file []
(doseq [line (read-lines "myfile.txt")]
(println line)))
defn
आइडोमैटिक क्लोजर है। आपका read-next-line
, जहाँ तक मैं समझता हूँ, आपके read-lines
कार्य के बाहर दिखाई दे रहा है । आप एक (let [read-next-line (fn [] ...))
बजाय इस्तेमाल किया हो सकता है ।
(require '[clojure.java.io :as io])
(io/copy (io/file "/etc/passwd") \*out*\)
फ़ाइल लाइन को लाइन से पढ़ने के लिए आपको अब इंटरोप का सहारा लेने की आवश्यकता नहीं है:
(->> "data.csv"
io/resource
io/reader
line-seq
(drop 1))
यह मानता है कि आपकी डेटा फ़ाइल संसाधन निर्देशिका में रखी गई है और पहली पंक्ति हेडर की जानकारी है जिसे खारिज किया जा सकता है।