2011-12-19 74 views
6

我正在使用此函数在Clojure中写入文件。在Clojure中写入文件


(defn writelines [file-path lines] 
    (with-open [wtr (clojure.java.io/writer file-path)] 
    (doseq [line lines] (.write wtr line)))) 

但这始终生成此错误:

IllegalArgumentException No matching method found: write for 
class java.io.BufferedWriter in 
clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:79) 

我在做什么错在这里?

+0

为了增加清晰度,你可以在你的问题中添加一个示例函数调用吗?这很可能证实opqdonut的答案。 – Gert 2011-12-19 08:42:43

+0

不是您的问题的答案,但可能在此上下文中有趣:http://stackoverflow.com/questions/7756909/in-clojure-1-3-how-to-read-and-write-a-file/ 7757674#7757674 – 2011-12-19 16:40:22

回答

17

首先,你的函数工作得很好了许多输入:

Clojure 1.3.0 
user=> (defn writelines [file-path lines] 
    (with-open [wtr (clojure.java.io/writer file-path)] 
    (doseq [line lines] (.write wtr line)))) 
#'user/writelines 
user=> (writelines "foobar" ["a" "b"]) 
nil 
user=> (writelines "quux" [1 2]) 
nil 

但是,当您尝试在一些奇怪的传递,我们得到的错误你描述:

user=> (writelines "quux" [#{1}]) 
IllegalArgumentException No matching method found: write for class java.io.BufferedWriter clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:79) 

此错误是因为BufferedWriter有多个重载版本write,clojure不知道要调用哪一个版本。在这种情况下,冲突的是write(char[])write(String)。使用字符串("a")和整数(1)这样的输入,clojure知道调用String版本的方法,但使用clojure无法决定的其他内容(例如clojure集合,#{1})。

如何确保writelines的输入确实是String s或使用str函数对它们进行了字符串化?另外,看看spit function

+0

注意:如果要将任意嵌套的Clojure值串化,最好使用'pr-str'而不是'str'。如果生成的字符串直接输入到流中,则应该使用'pr'(或'prn'),而不是两个步骤的'pr-str',然后使用'print'或'.write'。 – raek 2011-12-19 17:02:36

0

通过异常消息,行不是字符串,整数(字符)或int数组的序列。

1

试试这个:

(defn writelines [file-path lines] 
    (with-open [wtr (clojure.java.io/writer file-path)] 
    (binding [*out* wtr] 
     (doseq [line lines] (print wtr line))))) 

如果你看一下文档BufferedWriter你会看到你打电话write方式没有相应的方法(哎呦,我错过了继承的方法,我傻!)。我认为绑定到*out*更容易,除非你也想输出调试信息,在这种情况下它可能会有点棘手)。