2009-10-07 65 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

使用啜食閱讀
使用(合理大小的文件)吐他們再次寫回出來

相關問題