The with-openmakro mengurus bahwa pembaca ditutup pada akhir tubuh. Fungsi pembaca memaksa sebuah string (itu juga dapat melakukan URL, dll) menjadi a BufferedReader. line-seqmemberikan seq malas. Menuntut elemen berikutnya dari hasil malas menjadi baris yang sedang dibaca dari pembaca.
Perhatikan bahwa dari Clojure 1.7 dan selanjutnya, Anda juga dapat menggunakan transduser untuk membaca file teks.
Nomor 3: cara menulis ke file baru.
(use 'clojure.java.io)(with-open [wrtr (writer "/tmp/test.txt")](.write wrtr "Line to be written"))
Sekali lagi, with-openberhati-hatilah agar BufferedWriterditutup di ujung tubuh. Writer memaksa string menjadi BufferedWriter, yang Anda gunakan gunakan melalui java interop:(.write wrtr "something").
Anda juga bisa menggunakan spit, kebalikan dari slurp:
(spit "/tmp/test.txt""Line to be written")
Nomor 4: tambahkan baris ke file yang ada.
(use 'clojure.java.io)(with-open [wrtr (writer "/tmp/test.txt":append true)](.write wrtr "Line to be appended"))
Sama seperti di atas, tetapi sekarang dengan opsi tambahkan.
Atau lagi dengan spit, kebalikan dari slurp:
(spit "/tmp/test.txt""Line to be written":append true)
PS: Untuk lebih eksplisit tentang fakta bahwa Anda membaca dan menulis ke File dan bukan sesuatu yang lain, Anda bisa membuat objek File terlebih dahulu dan kemudian memaksa menjadi BufferedReaderatau Penulis:
Terima kasih banyak atas jawaban terinci Anda. Saya senang mengetahui cara direkomendasikan File IO (file teks) di 1.3. Tampaknya ada beberapa perpustakaan tentang File IO (clojure.contrb.io, clojure.contrib.duck-stream dan beberapa contoh langsung menggunakan Java BufferedReader FileInputStream InputStreamReader) yang membuat saya lebih membingungkan. Selain itu ada sedikit informasi tentang Clojure 1.3 terutama dalam bahasa Jepang (bahasa alami saya) Terima kasih.
jolly-san
Hai jolly-san, tnx untuk menerima jawaban saya! Untuk informasi Anda, clojure.contrib.duck-stream sekarang tidak digunakan lagi. Ini mungkin menambah kebingungan.
Michiel Borkent
Artinya, (with-open [rdr (reader "/tmp/test.txt")] (line-seq rdr))menghasilkan IOException Stream closedbukan kumpulan garis. Apa yang harus dilakukan? Saya mendapatkan hasil yang baik dengan jawaban oleh @ satyagraha.
0dB
4
Ini ada hubungannya dengan kemalasan. Ketika Anda menggunakan hasil baris-seq di luar dengan-terbuka, yang terjadi ketika Anda mencetak hasilnya ke REPL, maka pembaca sudah ditutup. Solusi adalah dengan membungkus baris-seq di dalam sebuah doall, yang memaksa evaluasi segera. (with-open [rdr (reader "/tmp/test.txt")] (doall (line-seq rdr)))
Michiel Borkent
Untuk pemula yang sebenarnya seperti saya, perhatikan bahwa doseqpengembalian nilyang dapat menyebabkan waktu sedih-tidak-kembali-nilai.
Oktober
33
Jika file tersebut sesuai dengan memori, Anda dapat membaca dan menulisnya dengan slurp dan meludah:
(def s (slurp "filename.txt"))
(sekarang berisi konten file sebagai string)
(spit "newfile.txt" s)
Ini menciptakan newfile.txt jika tidak keluar dan menulis konten file. Jika Anda ingin menambahkan file yang dapat Anda lakukan
(spit "filename.txt" s :append true)
Untuk membaca atau menulis file secara linier, Anda akan menggunakan pembaca dan penulis Java. Mereka dibungkus dalam namespace clojure.java.io:
Perhatikan bahwa perbedaan antara contoh slurp / spit dan pembaca / penulis adalah bahwa file tetap terbuka (dalam pernyataan let) di yang terakhir dan membaca dan menulis buffer, sehingga lebih efisien ketika berulang kali membaca dari / menulis ke file.
Paul terima kasih. Saya bisa belajar lebih banyak dengan kode Anda dan komentar Anda yang jelas pada titik fokus pada menjawab pertanyaan saya. Terima kasih banyak.
jolly-san
Terima kasih telah menambahkan informasi tentang metode tingkat sedikit lebih rendah yang tidak diberikan dalam jawaban (luar biasa) Michiel Borkent tentang metode terbaik untuk kasus-kasus tertentu.
Mars
@ Mars, terima kasih. Sebenarnya saya memang menjawab pertanyaan ini terlebih dahulu, tetapi jawaban Michiel memiliki lebih banyak struktur dan itu tampaknya sangat populer.
Paul
Ia melakukan pekerjaannya dengan baik pada kasus-kasus yang biasa, tetapi Anda memberikan informasi lain. Itu sebabnya bagus kalau SE memungkinkan banyak jawaban.
Mars
6
Mengenai pertanyaan 2, seseorang terkadang ingin aliran garis dikembalikan sebagai objek kelas satu. Untuk mendapatkan ini sebagai urutan malas, dan masih memiliki file ditutup secara otomatis pada EOF, saya menggunakan fungsi ini:
Saya tidak berpikir bersarang defnadalah Clojure yang ideomatik. Anda read-next-line, sejauh yang saya mengerti, terlihat di luar read-linesfungsi Anda . Anda mungkin menggunakan yang (let [read-next-line (fn [] ...))sebaliknya.
kristianlm
Saya pikir jawaban Anda akan sedikit lebih baik jika mengembalikan fungsi yang dibuat, (menutup pembaca terbuka) daripada mengikat secara global.
Ward
1
Ini adalah cara membaca seluruh file.
Jika file ada di direktori sumber daya, Anda dapat melakukan ini:
Jawaban:
Dengan asumsi kita hanya melakukan file teks di sini dan bukan beberapa hal biner gila.
Nomor 1: cara membaca seluruh file ke dalam memori.
Tidak disarankan saat ini adalah file yang sangat besar.
Nomor 2: cara membaca file baris demi baris.
The
with-open
makro mengurus bahwa pembaca ditutup pada akhir tubuh. Fungsi pembaca memaksa sebuah string (itu juga dapat melakukan URL, dll) menjadi aBufferedReader
.line-seq
memberikan seq malas. Menuntut elemen berikutnya dari hasil malas menjadi baris yang sedang dibaca dari pembaca.Perhatikan bahwa dari Clojure 1.7 dan selanjutnya, Anda juga dapat menggunakan transduser untuk membaca file teks.
Nomor 3: cara menulis ke file baru.
Sekali lagi,
with-open
berhati-hatilah agarBufferedWriter
ditutup di ujung tubuh. Writer memaksa string menjadiBufferedWriter
, yang Anda gunakan gunakan melalui java interop:(.write wrtr "something").
Anda juga bisa menggunakan
spit
, kebalikan darislurp
:Nomor 4: tambahkan baris ke file yang ada.
Sama seperti di atas, tetapi sekarang dengan opsi tambahkan.
Atau lagi dengan
spit
, kebalikan darislurp
:PS: Untuk lebih eksplisit tentang fakta bahwa Anda membaca dan menulis ke File dan bukan sesuatu yang lain, Anda bisa membuat objek File terlebih dahulu dan kemudian memaksa menjadi
BufferedReader
atau Penulis:Fungsi file juga di clojure.java.io.
PS2: Kadang-kadang berguna untuk dapat melihat apa direktori saat ini (jadi ".") Adalah. Anda bisa mendapatkan jalur absolut dengan dua cara:
atau
sumber
(with-open [rdr (reader "/tmp/test.txt")] (line-seq rdr))
menghasilkanIOException Stream closed
bukan kumpulan garis. Apa yang harus dilakukan? Saya mendapatkan hasil yang baik dengan jawaban oleh @ satyagraha.(with-open [rdr (reader "/tmp/test.txt")] (doall (line-seq rdr)))
doseq
pengembaliannil
yang dapat menyebabkan waktu sedih-tidak-kembali-nilai.Jika file tersebut sesuai dengan memori, Anda dapat membaca dan menulisnya dengan slurp dan meludah:
(sekarang berisi konten file sebagai string)
Ini menciptakan newfile.txt jika tidak keluar dan menulis konten file. Jika Anda ingin menambahkan file yang dapat Anda lakukan
Untuk membaca atau menulis file secara linier, Anda akan menggunakan pembaca dan penulis Java. Mereka dibungkus dalam namespace clojure.java.io:
Perhatikan bahwa perbedaan antara contoh slurp / spit dan pembaca / penulis adalah bahwa file tetap terbuka (dalam pernyataan let) di yang terakhir dan membaca dan menulis buffer, sehingga lebih efisien ketika berulang kali membaca dari / menulis ke file.
Berikut ini informasi lebih lanjut: slurp spit clojure.java.io Java BufferedReader Java's Writer
sumber
Mengenai pertanyaan 2, seseorang terkadang ingin aliran garis dikembalikan sebagai objek kelas satu. Untuk mendapatkan ini sebagai urutan malas, dan masih memiliki file ditutup secara otomatis pada EOF, saya menggunakan fungsi ini:
sumber
defn
adalah Clojure yang ideomatik. Andaread-next-line
, sejauh yang saya mengerti, terlihat di luarread-lines
fungsi Anda . Anda mungkin menggunakan yang(let [read-next-line (fn [] ...))
sebaliknya.Ini adalah cara membaca seluruh file.
Jika file ada di direktori sumber daya, Anda dapat melakukan ini:
ingat untuk meminta / menggunakan
clojure.java.io
.sumber
sumber
Untuk membaca file baris demi baris, Anda tidak perlu lagi melakukan interop:
Ini mengasumsikan bahwa file data Anda disimpan di direktori sumber daya dan bahwa baris pertama adalah informasi header yang dapat dibuang.
sumber