2013-04-24 108 views
4

我想從文本文件中讀取特定的行,但是我不想將文件加載到內存中(它可以變得非常大)。Java閱讀第n行

我一直在尋找,但我發現每一個例子都需要閱讀每一行(這會減慢我的代碼,因爲有超過100,000行)或將整個東西加載到數組中,並獲得正確的元素(文件將有很多行輸入)。

什麼,我想要做的一個例子:

String line = File.getLine(5); 

「的代碼是不實際的代碼,它是由以顯示我想要什麼」的原則

有沒有辦法做到這個?

----- -----編輯

我剛剛意識到這個文件將被寫入過在讀線之間(添加到文件的末尾)。

+2

通過100000行文件的每一行讀取是一個非常快速的操作,爲什麼你認爲這是一個問題? – Keppil 2013-04-24 19:59:43

+1

[skip](http://docs.oracle.com/javase/7/docs/api/java/io/Reader.html#skip(long))怎麼樣?但是,你需要一個固定的行長度或每行的行起始位置,或者至少想到行長度和每行唯一的ID(在這種情況下,你可能需要一個[隨機訪問文件](http:///docs.oracle.com/javase/tutorial/essential/io/rafs.html)如果你超調)。 – Dukeling 2013-04-24 20:04:06

+0

嘗試在RandomAccessFile中使用seek(long pos)方法,然後使用readLine()獲取數據。 – VKPRO 2013-04-24 20:08:44

回答

12

有沒有辦法做到這一點?

除非行的每個字節都是固定的字節數,否則不行。

實際上你不必保持記憶中的每一行 - 但是你必須通讀整個文件才能到達你想要的行,否則你將不知道從哪裏開始閱讀。

+0

哦,好吧我猜我必須逐行閱讀它,除非如果什麼劫下面說的工作。它仍然一行一行地閱讀它,但是你需要映射哪一行是什麼偏移量,所以你可以將指針移動到你想要的位置。 – NoLiver92 2013-04-25 07:42:38

3

必須逐行讀取文件中的行。否則,你如何知道何時到達第5行(如你的例子)?

編輯:

你可能也想看看Random Access Files這可能是有用的,如果你知道每行有多少字節,因爲喬恩斯基特說。

+2

準確地,甚至在隨機訪問文件中,你也不能逐行閱讀 - 只需通過字節。重要的是要記住,行(在文件系統上的文件中)由換行符任意表示。一個1KB的文件可能有1024行,或者只有一行 – darkpbj 2013-04-24 20:05:15

+0

@darkpbj RandomAccessFile有一個readLine()方法,所以我認爲你的意思是說RandomAccessFile不能按順序_seek_。 – rob 2013-04-25 05:09:33

0

做到這一點的唯一方法是沒有辦法隨機從一開始訪問基於索引的行生成的每一行是(你只需要記錄每一行的末尾)的索引,你有讀取該行之前的每個字節。

順便說一句:讀取100,000行可能只需要一秒鐘的快速機器。

3

要做到這一點是使用一個BufferedReader(http://docs.oracle.com/javase/1.5.0/docs/api/java/io/BufferedReader.html),因爲你可以指定你的緩衝區大小的最簡單方法。你可以這樣做:在=新的BufferedReader

的BufferedReader(新的FileReader( 「foo.in」),1024);

in.readLine(); 
in.readLine(); 
in.readLine(); 
in.readLine(); 
String line = in.readLine(); 
0

如果性能是這裏的大問題,你經常從一個靜態文件中讀取隨機線,那麼你可以通過該文件的起始閱讀和建立索引(基本上只是一個long[])有點優化這個文件每一行的偏移量。

一旦你有了這個,你知道確切位置,跳轉到文件中,然後你可以閱讀到下一個換行符檢索完整行。

2

1)讀了用戶選擇的線路,

如果你只需要讀取用戶選擇的線路一次或很少(如果該文件是足夠小),那麼你就必須從頭開始逐行讀取文件,直到您到達選定的行。

另一方面,如果您需要頻繁讀取用戶選擇的行,則應該建立行號和偏移量的索引。因此,例如,第42行對應於文件中的2347字節的偏移量。因此,理想情況下,您只能讀取整個文件一次並存儲索引 - 例如,在地圖中,將行號用作鍵和偏移量作爲值。

2)讀取自 上次讀取以來增加的新行數。我計劃每10秒讀一次這個文件。我有 行數,可以找到新的行號,但我需要 讀取線

對於第二點,你可以簡單地保存而不是保存當前行當前偏移到文件數量 - 但如果繼續提供顯着的績效收益,繼續構建指數肯定不會受到傷害。

  1. 使用RandomAccessFile.seek(長偏移量)的文件指針設置爲最近保存的偏移量(確認文件是不是最近保存第一偏移長 - 如果不是,什麼新東西已被追加)。
  2. 使用RandomAccessFile.readLine()來讀取行的文件
  3. 呼叫RandomAccessFile.getFilePointer()來獲取當前讀取行之後偏移和可選放(currLineNo + 1,偏移量)入索引。
  4. 重複步驟2-3直到到達文件末尾。

但是,除非性能已經成問題或極有可能成爲問題,否則不要過分關注性能優化。

+0

這看起來不錯,今晚我回家後我會試試(今天不得不上班)謝謝 – NoLiver92 2013-04-25 07:40:36

0

這裏是我讀過一個文件的代碼片斷,每10行寫一行,包括第一行到新文件(writer)。你可以隨時用你想做的任何事情替換try部分。要更改要讀取的行數,只需將if語句「lc.endsWith(」0「)」中的0更改爲您想要讀取的任何行。但是,如果在讀取文件時正在寫入文件,則此代碼只能在運行此代碼時與文件內包含的數據一起使用。

  LineNumberReader lnr = new LineNumberReader(new FileReader(new File(file))); 
      lnr.skip(Long.MAX_VALUE); 
      int linecount=lnr.getLineNumber(); 
      lnr.close(); 

     for (int i=0; i<=linecount; i++){ 

      //read lines 
      String line = bufferedReader.readLine(); 
      String lc = String.valueOf(i); 

      if (lc.endsWith("0")){ 

       try{ 

        writer.append(line+"\n"); 
        writer.flush(); 

        }catch(Exception ee){ 
       } 
      } 
     }