2014-02-22 12 views
0

我有450萬個條目的空間分離的數據文件中的格式如下如何迭代處理大數據文件?

CO_1 A 0 0 0 0 1

CO_2 A 0 0 0 0 1

該數據文件被用作Self-Organizing Map (SOM)算法的輸入,該算法遍歷該文件100(在我的情況下)迭代。

我使用下面的readFile函數將文件完全複製到臨時字符串中,並將該字符串傳遞給SOM算法。

public String readFile() 
{ 
    String temp = ""; 

    try 
    { 
     FileReader file = new FileReader(FILE_LOCATION); 
     BR = new BufferedReader(file); 
     String strLine = null; 

     while((strLine = BR.readLine()) != null) 
     { 
      temp += strLine + "\n"; 
     } 
    } 
    catch(Exception e) 
    { 

    } 

    return temp; 
} 

如何過,我覺得上面的方法把一個沉重的負擔,對內存和減慢,可能導致內存溢出的迭代。目前,我在具有30GB內存分配的集羣中運行此代碼,並且執行甚至還沒有完成約36小時的一次迭代。

我不能部分讀取文件(如在塊的行中),因爲一旦初始塊完成後SOM將不得不輪詢數據,這可能導致進一步的複雜性。

任何想法,我可以改善這一點,所以我可以成功迭代450萬條目100次。

EDIT

整個文件被讀入到使用上述方法僅一次的字符串。然後在整個100次迭代中使用字符串變量。但是,每次字符串標記器已被用來處理文件*迭代次數中的每一行。

+0

你能用更高效的數據結構來表示你的文件嗎?例如,如何使用''map.put(1,new BitSet())''形式的條目''Map ''''''您可以使用鍵「1」來表示字符串''CO_1''和一個包含「0 0 0 0 1''的位集來表示你的字符串的其餘部分? – gdiazc

+0

@Synex你有沒有嘗試分析你的代碼,看看哪部分是最長的? – Alan

+0

@Alan no我沒有。有什麼建議麼?我正在使用Eclipse IDE – Synex

回答

2

永遠不要使用字符串連接來實現這種目的。
而不是String,爲此目的使用StringBuffer類。
考慮下面的例子:

public StringBuffer readFile() 
{ 
    StringBuffer tempSB = new StringBuffer(); 

    try 
    { 
     FileReader file = new FileReader(FILE_LOCATION); 
     BR = new BufferedReader(file); 
     String strLine = null; 

     while((strLine = BR.readLine()) != null) 
     { 
      tempSB.append(strLine); 
      tempSB.append("\n"); 
     } 
    } 
    catch(Exception e) 
    { 

    } 

    return temp; 
} 

這將節省您的堆內存。

+0

在這種情況下,既然你知道大致預計有多少數據可能是指定StringBuffer的初始容量的明智因素,因此它不必花費年齡重新調整大小。例如:'= new StringBuffer(typical_line_length * rough_number_of_lines);' – Alan

+0

您可以在這裏使用'StringBuilder',因爲您不需要同步。 – qqilihq

+0

如果你需要搜索任何文本,那麼你應該去''Lucene索引''。 – unknown

0

用String + =讀取文件非常昂貴。我建議你將條目解析爲數據結構,這應該大約需要1-10秒。重複迭代應該少於一秒。每個條目使用110個字節的450萬個條目應該使用大約0.5 GB,也許1 GB用於更復雜的結構。這應該不足以擔心。

0

,如果你需要解析TXT 串行文件,並能夠讀取它隨機,使用持久存儲,就像一個SQL DB或no-SQL一個甚至Lucene Search Engine。 這會給你喜歡的好處:

  • 您不必到整個文件加載到RAM
  • 你可以使用流處理 - >讀取文件中的行由行,只保留RAM中的實際行
  • 解析和保留源文件需要花費更多時間,但隨機訪問會更快。
  • 甚至可以通過分析在多個線程讀取數據獨立
+0

如果有更多的數據,這可能是一個好主意,但Synex只在這裏處理一個相對較小的集合,所以我認爲使用一個數據庫會是矯枉過正的。每條記錄都是一個簡短的字符串,一個字符和5個數字。這可以解釋爲每個條目少於100個字節,因此小於0.5GB。假設一臺體面的機器,這應該不成問題。 – Alan

+0

好吧,36 ++小時的處理時間和30GB RAM *已經是過度殺傷:)無論如何,人們只需要設置一次數據庫一次,所以即使從短期的角度來看,它也應該得到回報 – injecteer

+0

我同意與@Alan。由於文件大小似乎大約爲100 MB,因此在這種情況下,內存中的解決方案更爲合適。 – gdiazc

2

我想補充其他的答案。儘管我認爲你應該將數據存儲在一個更有效的數據結構中,而不僅僅是一個字符串,但我認爲你編寫代碼的另一個原因可能很慢。

由於您的文件大小似乎在100 MB左右,您的代碼可能會變慢,因爲Eclipse尚未爲其分配足夠的堆空間。嘗試添加以下標誌:

-Xmx4G 

這會給你的代碼4 GB的堆空間的工作。要做到這一點,在Eclipse中去:

// Run -> Run Configurations -> <Select your main class on the left> 
// -> <Select the 'Arguments' tab> 
// -> <Add the string "-Xmx4G" to the 'VM arguments' text area> 

這可能會加速!