2009-10-07 45 views
1

现在我有有更简单的方法来将BufferedReader更改为字符串吗?

;; 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类),它给了我 “[email protected]

  • 以上循环太慢,而且内存空间不足。

+0

BufferedReader下的流有多大? – 2009-10-07 21:40:04

+0

它真的很大。它必须至少有10 MB。 – unj2 2009-10-08 01:01:09

回答

5
(clojure.contrib.duck-streams/slurp* your-buffer) ; is what you want 

你的代码很慢,因为缓冲区没有被暗示。

+0

如何提示? – unj2 2009-10-08 14:15:04

+0

(defn buffer-> string [#^ java.io.BufferedReader buffer] 参见http://clojure.org/java_interop#toc35 – cgrand 2009-10-10 08:36:06

+0

确保clojure告诉你任何未被暗示的东西: 打开* warn- on-reflection *。 http://clojure.org/api#toc27 – Leonel 2009-10-14 22:17:45

0

buffer.ToString()?或者在你的情况下,也许(.toString缓冲区)?

+1

我得到1:5 Trial =>(str * yyy *)=>“[email protected]” – unj2 2009-10-07 20:48:03

3

我不知道Clojure,所以我不能告诉你是否在代码中有一些细节错误,但使用StringBuffer并逐行添加输入是正确的方法(使用StringBuilder初始化为预期的最终规模,如果知道会带来重大但不显着的改进)。

如果内存不足,那么BufferedReader的内容可能太大而无法放入内存中,并且无法将其作为单个字符串使用 - 在这种情况下,您必须增加堆大小或找到一种方法来一次处理一小块数据。

顺便说一句,如果您知道输入的大小,更有效的方法是使用CharBuffer并使用Reader.read()填充它(您必须注意返回方法并在循环中使用它) 。

0

在java中你会做类似的事情;

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(); 
} 
0

我不知道clojure,只是Java。让我们从那里工作。

几点考虑:

  • 如果你的目标JVM版本为> = 1.5,你可以使用StringBuilder的代替的StringBuffer一个小的性能改进(没有同步,你不需要它)。阅读在这里

    http://java.sun.com/j2se/1.5.0/docs/api/java/lang/StringBuilder.html

  • 可是你的大性能成本大概是在缓冲存储器的扩展。当你实例化一个StringBuffer/StringBuilder而不使用容量参数的构造函数,你会得到一个小容量。

    当以小容量(内部缓冲区大小)开始时,您有很多扩展 - 每次超过该容量时,其内部缓冲区会重新分配到一个新容量,只是足够容纳新添加的文本,这意味着将之前保存的所有文本复制到新缓冲区。

    当您将更多文本附加到已经很大的字符串时,这会非常缓慢。

    如果您可以访问正在阅读的文本的大小(文件大小将近似),则可以显着减少扩展的数量。

  • 我也可以告诉你用阅读()的的BufferedReader方法中,一个有3个参数,这一个:

    BufferedReader.read(的char [],INT,INT)

    然后,您可以使用字符串的类构造函数接受一个字符阵列中的一个给焦炭缓冲区转换为字符串

    String.String(的char [],INT,INT)

    ...但是,我怀疑是性能的提高也不会那么大,特别是与减少多少的一个比较StringBuilder扩展您将拥有。

  • 逼近,你似乎无论有内存容量问题:

    最终作为整个文本所占用你将需要至少两倍的内存。

    要么如果使用StringBuilder的/StringBuffer的方法或另一种,最终你将不得不文本内容复制到新串保持的结果。

在你可能会需要解决此框的末尾:

  • 你确定你只有一个的BufferedReader作为一个起点和一个字符串作为结束了吗?你应该提供更广阔的图景!

如果这是最广泛的,那么您至少需要一个配置更多堆的JVM实例,因为无论如何您可能会用尽内存。

+0

实际上,StringBuffer和StringBuilder将*不足以保存新的长度 - 底层数组将会*双倍*(除非足够),这对扩展的数量构成了严格的限制。 – 2009-10-08 08:06:24

+0

你是对的,我站在纠正。 我有这个想法,然后错过了AbstractCapacity()的第一行的AbstractStringBuilder源代码(当双重检查时)。 但是对于目前的情况仍然意味着: 1)内存溢出的风险增加; 2)仍然有很多时间浪费在扩展上。 2)呃...那里并且完成了它,就像那个......几代CPU之前。 – 2009-10-09 17:16:45

0

使用啜食阅读
使用(合理大小的文件)吐他们再次写回出来

相关问题