如何从文件中一次读取一行文本,并将文本分配给Clojure中的变量
我想在Clojure中打开一个大型XML文件,每行处理一行文本,然后将选定的字符串转储到工作文件中 我对这个完全陌生,所以现在我只想能够(1)读取一个文件,(2)将选择分配给一个变量。我将处理大型XML文件,因此不能选择slurping 不管怎样,我正在使用从教程中获得的代码。每当我在REPL中执行它时,它都会打印出文件中包含的文本,但似乎无法创建变量str1(未解决的符号错误) 代码如下:如何从文件中一次读取一行文本,并将文本分配给Clojure中的变量,clojure,io,Clojure,Io,我想在Clojure中打开一个大型XML文件,每行处理一行文本,然后将选定的字符串转储到工作文件中 我对这个完全陌生,所以现在我只想能够(1)读取一个文件,(2)将选择分配给一个变量。我将处理大型XML文件,因此不能选择slurping 不管怎样,我正在使用从教程中获得的代码。每当我在REPL中执行它时,它都会打印出文件中包含的文本,但似乎无法创建变量str1(未解决的符号错误) 代码如下: (defn readfile [] (let [str1 ;; I want the text
(defn readfile []
(let [str1 ;; I want the text inside the text file to fill this variable
(with-open [rdr (io/reader "resources/loremipsum.txt")]
(reduce conj [] (line-seq rdr)))] str1))
(readfile)
在
let
中声明的绑定仅在let
主体中可见。由于readfile
函数返回文件的行,因此可以创建一个var并将调用函数的结果分配给它:
(def lines (readfile))
这里列出的代码是正确的,在复制和粘贴过程中是否发生了更改
user=> (require '[clojure.java.io :as io])
nil
(defn readfile []
(let [str1 (with-open [rdr (io/reader "lorum-lispsum")]
(reduce conj [] (line-seq rdr)))]
str1))
#'user/readfile
user=> (readfile)
["let lambda bind lambda let lambda"]
模式(reduce conj…
通常更容易使用写入函数
(defn readfile []
(let [str1 (with-open [rdr (io/reader "lorum-lispsum")]
(into [] (line-seq rdr)))]
str1))
由于进入
的作用是使其成为一个向量,同时将整个文件拉入内存,因此可以用调用vec
(defn readfile []
(let [str1 (with-open [rdr (io/reader "lorum-lispsum")]
(vec (line-seq rdr)))]
str1))
由于您还提到了不将整个文件存储在内存中是一个目标,因此我们可能希望重新安排内容以保持文件处于打开状态,同时将序列作为惰性序列进行处理
(require '[clojure.java.io :as io])
(defn process-a-line [line]
:your-code-here)
(defn the-main-part-of-my-program [lazy-sequence-of-lines]
(dorun (map process-a-line)))
(defn readfile []
(let [str1 (with-open [rdr (io/reader "lorum-lispsum")]
(line-seq rdr))]
(the-main-part-of-my-program str1)))
如果您试图在clojure中处理xml,我建议使用clojure.data.zip。下面是一个简单的例子:
(require '[clojure.xml :as xml])
(require '[clojure.zip :as zip])
(require '[clojure.data.zip.xml :as zf])
(import '[java.io ByteArrayInputStream])
(with-open [in-stream (ByteArrayInputStream. (.getBytes "
<xml>
<test>something</test>
<fish>dog</fish>
<test>something else</test>
</xml>"))]
(let [parsed (zip/xml-zip (xml/parse in-stream))]
(zf/xml-> parsed :xml :test zf/text)))
(需要“[clojure.xml:as-xml]”
(需要“[clojure.zip:as-zip]”)
(需要“[clojure.data.zip.xml:作为zf])
(导入“[java.io ByteArrayInputStream])
(在流中打开[ByteArrayInputStream.(.getBytes)”
某物
狗
别的
"))]
(让[parsed(zip/xml-zip(xml/parse-in-stream))]
(zf/xml->parsed:xml:test-zf/text)))
它将生成所提供选择器的延迟序列。使用XML通常是一种非常好的方法,可能适合您的需要。我相信字符串的值仅在LET body的范围内可用,Lee的最新帖子证实了这一点。您的示例使用惰性序列处理看起来很有希望。我认为这正是我的情况所需要的,我需要处理的文件和我必须筛选的数据量。顺便说一句,使用lorum lispsum进行智能移动。欣赏:)您的示例已经正确地放置了str1
名称的所有用法已经正确地将符号放置在let的范围内。它在[]
部分中给该符号一个值,然后将相同的值放入let绑定主体的返回位置。let表达式的主体是[]
是的,您关心的是正确的。确切地说,为什么str1的值不再可用。您能详细说明一下为什么要逐行处理大型XML文件吗?通常,您不能假设标记和内容包含在同一行中,这决定了解析器遵循“标记流”方法,但在您的情况下,可能会有所不同,这会改变建议。最初的计划是将XML转换为CSV,但是LOAD-INTO无法处理重复的标记,所以我不得不强行逐行读取文件以获取值。还需要做一些分类什么的,所以重新发明轮子似乎是一条路要走。