2010-09-28 13 views
6

मैं एक सूची में एक फाइल की सामग्री में पढ़ना चाहता हूँ। मेरे कुछ प्रयास अब तक रहे हैं -मैं लिस्प में किसी सूची में फ़ाइल की सामग्री कैसे पढ़ सकता हूं?

(defun get-file (filename) 
    (let ((x (open filename))) 
    (when x 
     (loop for line = (read-line x nil) 
    while line do (list line))) 
    (close x))) 

(defun get-file (filename) 
    (let ((x (open filename :if-does-not-exist nil)) (contents (list nil))) 
    (when x 
     (loop for line = (read-line x nil) 
    while line do (cons contents line))) 
    (close x) contents)) 

(defun get-file (filename) 
    (let ((x (open filename :if-does-not-exist nil)) (contents nil)) 
    (when x 
     (loop for line = (read-line x nil) 
    while line do (append contents line))) 
    (close x) contents)) 

इनमें से कोई भी काम नहीं किया। क्या कोई मुझे एक रास्ता बता सकता है? या इससे भी बेहतर - सभी सामग्री को सरणी में कैसे रखा जाए?

उत्तर

14

कैसे

(defun get-file (filename) 
    (with-open-file (stream filename) 
    (loop for line = (read-line stream nil) 
      while line 
      collect line))) 
+0

(साथ-खुली फ़ाइल (च फ़ाइल का नाम) तुम वहाँ फ़ाइल नाम से पहले एक च क्यों हैं? लाइन एकत्र करने क्या करता है? और अंत में लाइन के साथ सहयोग कैसे करता है? – Sterling

+3

'with-open-file'' फ़ाइल नाम 'नामक फ़ाइल खोलता है और स्ट्रीम को' f' से संबद्ध करता है। 'संग्रहण' सूची में 'line' के विभिन्न मान एकत्रित करता है, जब तक कि ''''' 'शून्य न हो। कॉमन लिस्प हाइपरस्पेक और प्रैक्टिकल कॉमन लिस्प आपके दोस्त हैं! –

+2

दूसरे शब्दों में, 'ओपन-फाइल' 'ओपन' और 'क्लोज़' और 'लेट' के सभी काम करता है। –

8

के बारे में कहाँ समस्याओं कर रहे हैं?

(defun get-file (filename) 
    (let ((x (open filename))) 
    (when x 
     (loop for line = (read-line x nil) 
      while line 
      do (list line))) ; <-- you are not collecting, just doing 
    (close x)))     ; <- the function returns the value of CLOSE 

(defun get-file (filename) 
    (let ((x (open filename :if-does-not-exist nil)) 
     (contents (list nil))) 
    (when x 
     (loop for line = (read-line x nil) 
      while line 
      do (cons contents line))) ; <-- again, the cons goes nowhere 
    (close x) contents))    ; <-- CONTENTS has never been changed 

(defun get-file (filename) 
    (let ((x (open filename :if-does-not-exist nil)) 
     (contents nil)) 
    (when x 
     (loop for line = (read-line x nil) 
      while line 
      do (append contents line))) ; <- again the result goes nowhere 
    (close x) contents))     ; <-- CONTENTS has never been changed 

DO साइड इफेक्ट्स के लिए कुछ निष्पादित करेगा।

संग्रह परिणाम एकत्र करेगा और एलओपीपी बाहर निकलने पर एकत्रित मूल्यों की एक सूची वापस कर देगा।

जैसा कि पहले से ही उल्लेख किया गया है, खोलने/बंद करने के बजाय ओपन-फ़ाइल का उपयोग करें। गतिशील क्षेत्र छोड़ने के साथ-साथ-खुली फ़ाइल फ़ाइल बंद कर देगी। सामान्य निकास से नहीं, बल्कि UNWIND-PROTECT का उपयोग करते हुए त्रुटि स्थितियों पर भी।

यदि आप किसी फ़ाइल की सामग्री को पढ़ना चाहते हैं, तो आप रीड-सेक्वेंस का उपयोग कर सकते हैं। सामान्य समस्याओं के साथ। उदाहरण के लिए जब आप एक स्ट्रिंग में टेक्स्ट के रूप में ASCII फ़ाइल पढ़ते हैं, तो स्ट्रिंग फ़ाइल से छोटी हो सकती है। उदाहरण के लिए आम लिस्प एक सीआरएलएफ को एक ही चरित्र के साथ प्रतिनिधित्व करेगा, प्लेटफार्मों पर जहां सीआरएलएफ नई लाइन है। एक और उदाहरण: यूनिकोड समर्थन कार्यान्वयन में फ़ाइल में यूटीएफ -8 कोड को एक वर्ण के साथ प्रतिस्थापित किया जा सकता है।

+0

+1! –

2

मैं में पुस्तकालयों जोड़ देंगे

संपादितuiop साथ, और भी आसान है, जो ASDF में शामिल है:।

(uiop:read-file-lines "file.txt") 

https://github.com/fare/asdf/blob/master/uiop/stream.lisp#L445

भी है

(uiop:read-file-string "file") 

Alexandria's read-file-into-string और विभाजन अनुक्रम के साथ

:

(alexandria:read-file-into-string "file.txt") 
(split-sequence:split-sequence #\Newline *) 

str के साथ:

(str:lines (str:from-file "file.txt")) 
संबंधित मुद्दे

 संबंधित मुद्दे