现在我有
;; buffer->string: BufferedReader -> String
(defn buffer->string [buffer]
(loop [line (.readLine buffer) sb (StringBuilder.)]
(if(nil? line)
(.toString sb)
(recur (.readLine buffer) (.append sb line)))))
这太慢了。
编辑:
我有一个BufferedReader
当我尝试(str BufferedReader)时,它给了我“java.io.BufferedReader@1ce784b”
上面的循环太慢,我的内存空间不足。
答案 0 :(得分:5)
(clojure.contrib.duck-streams/slurp* your-buffer) ; is what you want
您的代码很慢,因为没有暗示缓冲区。
答案 1 :(得分:3)
我不知道Clojure,所以我不知道你的代码中是否有一些细节错误,但使用StringBuffer
并逐行追加输入是正确的方法(嗯,使用StringBuilder
初始化为预期的最终大小(如果已知会带来重大但不显着的改进)。
如果内存不足,那么BufferedReader的内容可能太大而无法放入内存中,也无法将其作为单个字符串 - 在这种情况下,您必须增加您的堆大小或找到一种方法来一次处理一小块数据。
顺便说一句,如果您知道输入的大小,更有效的方法是使用CharBuffer并使用Reader.read()填充它(您必须注意返回方法)并在循环中使用它。答案 2 :(得分:0)
buffer.ToString()?或者在你的情况下,也许(.toString缓冲区)?
答案 3 :(得分:0)
public String getStringFromBuffer(){
BufferedReader bRead = new BufferedReader();
String line = null;
StringBuffer theText = new StringBuffer();
while((line=bRead.readLine())!=null){
theText.append(line+"\n);
}
return theText.toString();
}
答案 4 :(得分:0)
我不知道clojure,只是Java。让我们在那里工作。
需要考虑的一些要点:
如果您的目标JVM版本是> = 1.5,您可以使用 StringBuilder 而不是 StringBuffer 来实现小的性能提升(没有同步,你没有需要它)。在这里阅读它
http://java.sun.com/j2se/1.5.0/docs/api/java/lang/StringBuilder.html
但是你的巨大性能成本可能是缓冲扩展。当您在不使用带有capacity参数的构造函数的情况下实例化 StringBuffer / StringBuilder 时,您将获得较小的容量。
当以小容量(内部缓冲区大小)开始时,您有许多扩展 - 每次超过该容量时,其内部缓冲区将重新分配到新容量,大小足以容纳新附加的文本,这意味着复制所有以前保存的文本到新缓冲区。
当您将更多文字附加到已经非常大的字符串时,这非常慢。
如果您可以访问正在阅读的文本大小(文件大小是近似值),则可以显着减少扩展量。
我还可以告诉你使用 BufferedReader 的 read()方法,这个方法有3个参数,这一个:
BufferedReader.read(char [],int,int)
然后,您可以使用接受 char 数组的 String 的类构造函数之一将 char 缓冲区转换为字符串:
String.String(char [],int,int)
...但是,我怀疑性能提升不会那么大,特别是与减少你将拥有的 StringBuilder 扩展数量相比时。
无论近似值如何,您似乎都有内存容量问题:
最后,您需要的内存至少是整个文本占用的两倍。
如果您使用 StringBuilder / StringBuffer 方法或另一个方法,最后您必须将文本内容复制到保存结果的新String。
最后,你可能需要解决这个问题:
如果这是你所拥有的最广泛的,你至少需要一个配置了更多堆的JVM实例,因为无论如何你可能会使用这些解决方案的内存不足。
答案 5 :(得分:0)
使用 slurp 阅读(合理大小的文件) in
使用吐出将它们再次写回 out 。