2011-10-13 12 views
153

मैं क्लोजर 1.3 में फ़ाइल पढ़ने और लिखने के "अनुशंसित" तरीके को जानना चाहता हूं।क्लोजर 1.3 में, फ़ाइल को पढ़ने और लिखने के लिए

  1. पूरी फ़ाइल को पढ़ने के लिए कैसे
  2. कैसे
  3. किसी मौजूदा फ़ाइल
+1

Google का पहला परिणाम: http: //lethain.com/reading-file-in-clojure/ – jcubic

+7

यह परिणाम 200 9 से है, कुछ चीजें हाल ही में बदल दी गई हैं। वास्तव में – Sergey

+9

। यह StackOverflow प्रश्न अब Google पर पहला परिणाम है। – mydoghasworms

उत्तर

255

मान लिया जाये कि हम केवल कुछ कर रहे हैं यहाँ और नहीं कुछ पागल द्विआधारी सामान फ़ाइलें।

संख्या 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 मैक्रो देखभाल कि पाठक शरीर के अंत में बंद कर दिया है लेता है। पाठक फ़ंक्शन एक स्ट्रिंग को जोड़ता है (यह एक यूआरएल भी कर सकता है, आदि) BufferedReader में। line-seq एक आलसी सीक प्रदान करता है। आलसी seq के अगले तत्व की मांग पाठक से एक लाइन में पढ़ा जा रहा है।

ध्यान दें कि क्लोजर 1.7 से आगे, आप पाठ फ़ाइलों को पढ़ने के लिए transducers का भी उपयोग कर सकते हैं।

संख्या 3: एक नई फ़ाइल को कैसे लिखें।

(use 'clojure.java.io) 
(with-open [wrtr (writer "/tmp/test.txt")] 
    (.write wrtr "Line to be written")) 

फिर, with-open देखभाल कि BufferedWriter शरीर के अंत में बंद कर दिया है लेता है। लेखक एक BufferedWriter में एक स्ट्रिंग coerces, कि तुम जावा इंटरॉप के माध्यम से उपयोग का उपयोग करें:

(spit "/tmp/test.txt" "Line to be written") 

संख्या 4: (.write wrtr "something").

तुम भी spit, slurp के विपरीत इस्तेमाल कर सकते हैं किसी मौजूदा फ़ाइल के लिए एक लाइन संलग्न ।

(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) 
+1

आपके विस्तृत उत्तर के लिए बहुत बहुत धन्यवाद। 1.3 में फ़ाइल IO (टेक्स्ट फ़ाइल) के अनुशंसित तरीके को जानना मुझे खुशी है। वहाँ आईओ (clojure.contrb.io, clojure.contrib.duck धाराओं और कुछ उदाहरण सीधे जावा BufferedReader FileInputStream InputStreamReader का प्रयोग करके) जो मुझे और अधिक भ्रमित कर दिया फ़ाइल के बारे में कुछ पुस्तकालयों रहे हैं लगता है। इसके अलावा क्लोजर 1.3 के बारे में बहुत कम जानकारी है, खासकर जापानी (मेरी प्राकृतिक भाषा) धन्यवाद। –

+0

हाय जॉली-सान, टीएनएक्स मेरे जवाब को स्वीकार करने के लिए! आपकी जानकारी के लिए, clojure.contrib.duck-streams अब बहिष्कृत है। यह संभवतः भ्रम में जोड़ता है। –

+0

बहुत जानकारीपूर्ण। धन्यवाद। – octopusgrabbus

29

के लिए एक लाइन को जोड़ने के लिए कैसे एक नई फ़ाइल लिखने के लिए कैसे लाइन

  • द्वारा एक फ़ाइल लाइन को पढ़ने के लिए अगर फ़ाइल मेमोरी में फिट बैठती है तो आप इसे स्लर्प और थूक के साथ पढ़ और लिख सकते हैं:

    (def s (slurp "filename.txt")) 
    

    (spit "newfile.txt" s) 
    

    अगर यह बाहर निकलने नहीं करता और फ़ाइल सामग्री लिखते हैं इस newfile.txt बनाता है (रों अब एक स्ट्रिंग के रूप में एक फ़ाइल की सामग्री शामिल हैं)। आप फाइल करने के लिए संलग्न करने के लिए चाहते हैं तो आप

    (spit "filename.txt" s :append true) 
    

    कर पढ़ने के लिए या एक फ़ाइल लिखने के लिए linewise आप जावा के पाठक और लेखक का प्रयोग करेंगे कर सकते हैं। वे नाम स्थान 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/थूक और रीडर/राइटर उदाहरण के बीच अंतर यह है कि फ़ाइल उत्तरार्द्ध और में खुला रहता (दें बयान में) है पढ़ना और लिखना बफर किया जाता है, इस प्रकार बार-बार फ़ाइल से लिखने/लिखने पर अधिक कुशल होता है।

    यहाँ अधिक जानकारी है: slurpspit clojure.java.io Java's BufferedReader Java's Writer

  • +1

    धन्यवाद पॉल। मैं आपके कोड और आपकी टिप्पणियों से अधिक जान सकता हूं जो मेरे प्रश्न का उत्तर देने पर ध्यान केंद्रित करने वाले बिंदु में स्पष्ट हैं। आपका बहुत बहुत धन्यवाद। –

    +0

    सामान्य मामलों के लिए सर्वोत्तम तरीकों पर माइकल बोर्केंट (उत्कृष्ट) उत्तर में दिए गए कुछ निम्न-स्तरीय तरीकों पर जानकारी जोड़ने के लिए धन्यवाद। – Mars

    +0

    @ मर्स धन्यवाद। दरअसल मैंने पहले इस सवाल का जवाब दिया था, लेकिन माइकल के जवाब में अधिक संरचना है और यह बहुत लोकप्रिय प्रतीत होता है। – Paul

    6

    प्रश्न 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))) 
    
    +5

    मुझे नहीं लगता कि घोंसले 'defn' आदर्श क्लोजर है। जहां तक ​​मैं समझता हूं, आपकी 'रीड-अगली-लाइन', आपके 'रीड-लाइन' फ़ंक्शन के बाहर दिखाई दे रही है। हो सकता है कि आपने '' (रीड-अगली-पंक्ति (एफएन [] ...)) का उपयोग किया हो। – kristianlm

    1

    यह कैसे पूरी फ़ाइल को पढ़ने के लिए है: एक आलसी अनुक्रम के रूप में इस प्राप्त करने के लिए, और अभी भी फ़ाइल EOF पर अपने आप बंद है, मैं इस समारोह का इस्तेमाल किया।

    फ़ाइल संसाधन निर्देशिका में है, तो आप ऐसा कर सकते हैं:

    (let [file-content-str (slurp (clojure.java.io/resource "public/myfile.txt")])

    की आवश्यकता के लिए याद/उपयोग clojure.java.io

    0
    (require '[clojure.java.io :as io]) 
    (io/copy (io/file "/etc/passwd") \*out*\) 
    
    संबंधित मुद्दे