Clojure 1.3 এ, কীভাবে একটি ফাইল পড়তে এবং লিখতে হয়


163

ক্লোজার ১.৩-এ ফাইল পড়ার এবং লেখার "প্রস্তাবিত" উপায়টি আমি জানতে চাই।

  1. কীভাবে পুরো ফাইলটি পড়বেন
  2. কীভাবে একটি ফাইল লাইন লাইন পড়তে হয়
  3. কিভাবে একটি নতুন ফাইল লিখবেন
  4. একটি বিদ্যমান ফাইলে কীভাবে একটি লাইন যুক্ত করবেন

2
গুগল থেকে প্রথম ফলাফল: lethain.com/reading-file-in-clojure
jcubic

8
এই ফলাফলটি ২০০৯ সাল থেকে, কিছু জিনিস ইদানীং পরিবর্তিত হয়েছে।
সের্গেই 21

11
প্রকৃতপক্ষে. এই স্ট্যাকওভারফ্লো প্রশ্নটি এখন গুগলে প্রথম ফলাফল।
mydoghasworms

উত্তর:


273

ধরে নেওয়া আমরা এখানে কেবল পাঠ্য ফাইল করছি এবং কিছু ক্রেজি বাইনারি স্টাফ নয়।

নম্বর 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, ইত্যাদি কাজ করতে পারেন) একটি মধ্যে coerces BufferedReaderline-seqএকটি অলস Sequ বিতরণ। অলস সিকের পরবর্তী উপাদানগুলির দাবি পাঠকের কাছ থেকে পড়া একটি লাইনে তৈরি করা।

নোট করুন যে ক্লোজুর ১.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)

1
আপনার বিস্তারিত উত্তরের জন্য আপনাকে অনেক ধন্যবাদ। আমি 1.3-তে ফাইল আইও (পাঠ্য ফাইল) এর প্রস্তাবিত উপায়টি জানতে পেরে আনন্দিত। ফাইল আইও (Clojure.contrb.io, Clojure.contrib.duck- স্ট্রিম এবং জাভা বাফারডারিডার ফাইলআইপুটপ্রবাহ ইনপুটস্ট্রিম রিডার ব্যবহার করে কিছু উদাহরণ) সম্পর্কে কিছু গ্রন্থাগার রয়েছে বলে মনে হয় যা আমাকে আরও বিভ্রান্ত করেছে। তবুও Clojure 1.3 সম্পর্কে খুব কম তথ্য আছে বিশেষত জাপানীজ (আমার প্রাকৃতিক ভাষা) আপনাকে ধন্যবাদ।
জলি-সান

হাই জলি-সান, আমার উত্তর গ্রহণের জন্য টিএনএক্স! আপনার তথ্যের জন্য, Clojure.contrib.duck- স্ট্রিমগুলি এখন হ্রাস করা হয়েছে। এটি সম্ভবত বিভ্রান্তি যুক্ত করে।
মিশিগেল বারকেন্ট

অর্থাৎ লাইন সংগ্রহের পরিবর্তে (with-open [rdr (reader "/tmp/test.txt")] (line-seq rdr))ফলন IOException Stream closedহয়। কি করো? যদিও @ সত্যগ্রহের উত্তর দিয়ে ভাল ফলাফল পাচ্ছি।
ডিবি

4
এই অলসতা সঙ্গে করতে হবে। আপনি যখন ওপেনের বাইরে লাইন-সেকের ফলাফল ব্যবহার করেন, যা আপনি যখন এর ফলাফলটি আরপিএলে প্রিন্ট করেন তখন ঘটে যায়, তারপরে পাঠক ইতিমধ্যে বন্ধ হয়ে গেছে। একটি সমাধান হ'ল একটি ডোলের মধ্যে লাইন-সিকটি মোড়ানো, যা তাত্ক্ষণিকভাবে মূল্যায়নকে বাধ্য করে। (with-open [rdr (reader "/tmp/test.txt")] (doall (line-seq rdr)))
মিশিগেল বারকেন্ট

আমার হিসাবে প্রকৃত নবীনদের জন্য, নোট করুন যে doseqরিটার্নগুলি nilদু: খ-না-প্রত্যাবর্তন-মূল্য বারের দিকে নিয়ে যেতে পারে।
অক্টোবর

33

যদি ফাইলটি মেমরির সাথে ফিট করে তবে আপনি স্লার্প এবং থুতু দিয়ে এটি পড়তে এবং লিখতে পারেন:

(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!"

নোট করুন যে স্লার্প / স্পিট এবং পাঠক / লেখকের উদাহরণগুলির মধ্যে পার্থক্যটি হ'ল ফাইলটি পরবর্তীকালে খোলা থাকে (লেট স্টেটমেন্টগুলিতে) এবং পড়া এবং লেখার বাফার হয়, এভাবে কোনও ফাইল থেকে বারবার / লেখার সময় বারবার পড়ার সময় আরও কার্যকর।

আরও তথ্যের হল: গবগব করে খাওয়া থুতু clojure.java.io জাভার BufferedReader জাভার রাইটার


1
আপনাকে ধন্যবাদ পল। আমি আপনার কোডগুলি এবং আপনার মন্তব্যে আরও শিখতে পারি যা আমার প্রশ্নের উত্তর দেওয়ার দিকে মনোযোগ নিবদ্ধ করে পয়েন্টে পরিষ্কার। আপনাকে অনেক ধন্যবাদ.
জলি-সান

সাধারণ ক্ষেত্রে সেরা পদ্ধতির জন্য মিশেল বোরকেন্টের (দুর্দান্ত) উত্তরে দেওয়া হয়নি এমন কিছুটা নিম্ন-স্তরের পদ্ধতি সম্পর্কে তথ্য যুক্ত করার জন্য ধন্যবাদ Thanks
মঙ্গল

@ মার্স ধন্যবাদ আসলে আমি প্রথমে এই প্রশ্নের উত্তর দিয়েছি, তবে মিশিগেলের উত্তরটির আরও কাঠামো রয়েছে এবং এটি খুব জনপ্রিয় বলে মনে হয়।
পল

তিনি সাধারন কেসগুলির সাথে একটি ভাল কাজ করেন তবে আপনি অন্যান্য তথ্য সরবরাহ করেছেন। সে কারণেই এটি ভাল যে এসই একাধিক উত্তর দেয়।
মঙ্গল

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)))

7
আমি মনে করি না বাসা defnবাঁধাই আদর্শিক ক্লোজার। আপনার read-next-line, যতদূর আমি বুঝতে পারি, আপনার read-linesফাংশনের বাইরে দৃশ্যমান । এর (let [read-next-line (fn [] ...))পরিবর্তে আপনি হয়ত ব্যবহার করেছেন ।
ক্রিশ্চিয়ানোম

আমি মনে করি আপনার উত্তরটি বিশ্বব্যাপী বাইন্ডিংয়ের পরিবর্তে তৈরি করা ফাংশন (উন্মুক্ত পাঠকের উপরে বন্ধ করে দেওয়া) ফিরিয়ে দিলে কিছুটা ভাল হতে পারে।
ওয়ার্ড

1

এভাবেই পুরো ফাইলটি পড়তে হবে।

ফাইলটি যদি রিসোর্স ডিরেক্টরিতে থাকে তবে আপনি এটি করতে পারেন:

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

প্রয়োজনীয় / ব্যবহার মনে রাখবেন clojure.java.io



0

লাইন দ্বারা একটি ফাইল লাইন পড়ার জন্য আপনাকে আর ইন্টারোপ অবলম্বন করতে হবে না:

(->> "data.csv"
      io/resource
      io/reader
      line-seq
      (drop 1))

এটি ধরে নিয়েছে যে আপনার ডেটা ফাইলটি সম্পদ ডিরেক্টরিতে রাখা হয়েছে এবং প্রথম লাইনটি শিরোনাম সম্পর্কিত তথ্য যা বাতিল করা যেতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.