with-openМакрос заботится о том , что читатель закрыт в конце тела. Функция читателя принуждает строку (она также может сделать URL, и т.д.) в BufferedReader. line-seqпоставляет ленивый seq. Требование следующего элемента ленивого seq приводит к строке, читаемой читателем.
Обратите внимание, что начиная с Clojure 1.7, вы также можете использовать преобразователи для чтения текстовых файлов.
Номер 3: как записать в новый файл.
(use 'clojure.java.io)(with-open [wrtr (writer "/tmp/test.txt")](.write wrtr "Line to be written"))
Опять же, with-openзаботится о том, чтобы BufferedWriterон был закрыт в конце тела. Writer приводит строку в BufferedWriter, которую вы используете, используя взаимодействие с Java:(.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)
PS: Чтобы быть более точным в том, что вы читаете и записываете в файл, а не во что-то еще, вы можете сначала создать объект File, а затем привести его к типу BufferedReaderили Writer:
Большое спасибо за ваш подробный ответ. Я рад узнать рекомендуемый способ ввода-вывода файла (текстовый файл) в 1.3. Кажется, было несколько библиотек о Файловом вводе-выводе (clojure.contrb.io, clojure.contrib.duck-streams и некоторые примеры, непосредственно использующие Java BufferedReader FileInputStream InputStreamReader), которые привели меня в замешательство. Более того, мало информации о Clojure 1.3, особенно на японском (мой естественный язык). Спасибо.
Веселый Сан
Привет, Джолли-сан, спасибо за ответ! Для вашей информации, clojure.contrib.duck-streams теперь устарела. Это, возможно, добавляет путаницы.
Михиль Боркент,
То есть (with-open [rdr (reader "/tmp/test.txt")] (line-seq rdr))выдает IOException Stream closedвместо набора строк. Что делать? Получаю хорошие результаты с ответом @satyagraha, хотя.
0 дБ
4
Это связано с ленью. Когда вы используете результат line-seq вне with-open, что происходит, когда вы печатаете его результат в REPL, считыватель уже закрыт. Решение состоит в том, чтобы обернуть строку-последовательность в doall, что немедленно вызывает оценку. (with-open [rdr (reader "/tmp/test.txt")] (doall (line-seq rdr)))
Михель Боркент
Для фактических начинающих, как я, обратите внимание, что doseqвозвращаетсяnil могут привести к временам грустного отсутствия возврата.
октября
33
Если файл помещается в память, вы можете прочитать и записать его с помощью slurp и spit:
(def s (slurp "filename.txt"))
(s теперь содержит содержимое файла в виде строки)
(spit "newfile.txt" s)
Это создает newfile.txt, если он не завершает работу и записывает содержимое файла. Если вы хотите добавить в файл, вы можете сделать
(spit "filename.txt" s :append true)
Для чтения или записи файла вы также должны использовать программу чтения и записи Java. Они заключены в пространство имен clojure.java.io:
Обратите внимание, что разница между slurp / spit и примерами чтения / записи заключается в том, что файл остается открытым (в операторах let) в последнем, а чтение и запись буферизуются, таким образом, более эффективно при многократном чтении / записи в файл.
Спасибо, Пол. Я мог бы узнать больше по вашим кодам и вашим комментариям, которые ясны в том, что касается ответа на мой вопрос. Большое спасибо.
Jolly-San
Спасибо за добавление информации о методах несколько более низкого уровня, не приведенных в ответе Михеля Боркента (отлично) о лучших методах для типичных случаев.
Марс
@Mars Спасибо. На самом деле я сначала ответил на этот вопрос, но у Михеля больше структуры, и это кажется очень популярным.
Пол
Он хорошо справляется с обычными делами, но вы предоставили другую информацию. Вот почему хорошо, что SE допускает несколько ответов.
Марс
6
Что касается вопроса 2, иногда хочется, чтобы поток строк возвращался как первоклассный объект. Чтобы получить это как ленивую последовательность и при этом автоматически закрывать файл в EOF, я использовал эту функцию:
Я не думаю, что вложение defnявляется идеологическим Clojure. Ваш read-next-line, насколько я понимаю, виден за пределами вашей read-linesфункции. Вы могли бы использовать (let [read-next-line (fn [] ...))вместо этого.
kristianlm
Я думаю, что ваш ответ был бы немного лучше, если бы он возвращал созданную функцию (закрывающуюся при открытом ридере), а не глобальную привязку.
Уорд
1
Это как прочитать весь файл.
Если файл находится в каталоге ресурсов, вы можете сделать это:
Ответы:
Предполагая, что мы делаем только текстовые файлы здесь, а не какие-то сумасшедшие бинарные вещи.
Номер 1: как прочитать весь файл в память.
Не рекомендуется, когда это действительно большой файл.
Номер 2: как читать файл построчно.
with-open
Макрос заботится о том , что читатель закрыт в конце тела. Функция читателя принуждает строку (она также может сделать URL, и т.д.) вBufferedReader
.line-seq
поставляет ленивый seq. Требование следующего элемента ленивого seq приводит к строке, читаемой читателем.Обратите внимание, что начиная с Clojure 1.7, вы также можете использовать преобразователи для чтения текстовых файлов.
Номер 3: как записать в новый файл.
Опять же,
with-open
заботится о том, чтобыBufferedWriter
он был закрыт в конце тела. Writer приводит строку вBufferedWriter
, которую вы используете, используя взаимодействие с Java:(.write wrtr "something").
Вы также можете использовать
spit
, противоположностьslurp
:Номер 4: добавить строку в существующий файл.
То же, что и выше, но теперь с опцией добавления.
Или снова с
spit
противоположностьюslurp
:PS: Чтобы быть более точным в том, что вы читаете и записываете в файл, а не во что-то еще, вы можете сначала создать объект File, а затем привести его к типу
BufferedReader
или Writer:Файловая функция также находится в clojure.java.io.
PS2: Иногда удобно видеть, что представляет собой текущий каталог (поэтому "."). Вы можете получить абсолютный путь двумя способами:
или
источник
(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
могут привести к временам грустного отсутствия возврата.Если файл помещается в память, вы можете прочитать и записать его с помощью slurp и spit:
(s теперь содержит содержимое файла в виде строки)
Это создает newfile.txt, если он не завершает работу и записывает содержимое файла. Если вы хотите добавить в файл, вы можете сделать
Для чтения или записи файла вы также должны использовать программу чтения и записи Java. Они заключены в пространство имен clojure.java.io:
Обратите внимание, что разница между slurp / spit и примерами чтения / записи заключается в том, что файл остается открытым (в операторах let) в последнем, а чтение и запись буферизуются, таким образом, более эффективно при многократном чтении / записи в файл.
Вот дополнительная информация: slurp spit clojure.java.io Java BufferedReader Java's Writer
источник
Что касается вопроса 2, иногда хочется, чтобы поток строк возвращался как первоклассный объект. Чтобы получить это как ленивую последовательность и при этом автоматически закрывать файл в EOF, я использовал эту функцию:
источник
defn
является идеологическим Clojure. Вашread-next-line
, насколько я понимаю, виден за пределами вашейread-lines
функции. Вы могли бы использовать(let [read-next-line (fn [] ...))
вместо этого.Это как прочитать весь файл.
Если файл находится в каталоге ресурсов, вы можете сделать это:
не забудьте требовать / использовать
clojure.java.io
.источник
источник
Чтобы читать файл построчно, вам больше не нужно прибегать к взаимодействию:
Это предполагает, что ваш файл данных хранится в каталоге ресурсов, а первая строка содержит информацию заголовка, которую можно отбросить.
источник