在 Java 中讀取檔案的最後 N 行
瀏覽人數:358最近更新:
一、簡介
在本文中,我們將了解如何使用不同的標準 Java 套件和 Apache Commons IO 庫從檔案中讀取最後 N 行.
2. 樣本數據
我們將在本教程中的所有範例中使用下面定義的範例資料和參數。
我們首先建立一個名為data.txt的簡單文件,將其用作輸入文件:
line 1
line 2
line 3
line 4
line 5
line 6
line 7
line 8
line 9
line 10
此外,我們將使用以下範例值:要讀取的最後 N 行數、要驗證的輸出以及檔案路徑:
private static final String FILE_PATH = "src/test/resources/data.txt";
private static final int LAST_LINES_TO_READ = 3;
private static final String OUTPUT_TO_VERIFY = "line 8\nline 9\nline 10";
3.使用BufferedReader
讓我們來探索BufferedReader類,它允許我們逐行讀取文件。它的優點是不將整個檔案儲存在記憶體中。我們可以使用Queue ,它是一種 FIFO 結構。當我們讀取檔案時,一旦 Q ueue大小達到要讀取的行數,我們將開始刪除第一個元素:
@Test
public void givenFile_whenUsingBufferedReader_thenExtractedLastLinesCorrect() throws IOException {
try (BufferedReader br = Files.newBufferedReader(Paths.get(FILE_PATH))) {
Queue<String> queue = new LinkedList<>();
String line;
while ((line = br.readLine()) != null){
if (queue.size() >= LAST_LINES_TO_READ) {
queue.remove();
}
queue.add(line);
}
assertEquals(OUTPUT_TO_VERIFY, String.join("\n", queue));
}
}
4. 使用Scanner
我們可以使用Scanner類別透過類似的方法獲得相同的結果:
@Test
public void givenFile_whenUsingScanner_thenExtractedLastLinesCorrect() throws IOException {
try (Scanner scanner = new Scanner(new File(FILE_PATH))) {
Queue<String> queue = new LinkedList<>();
while (scanner.hasNextLine()){
if (queue.size() >= LAST_LINES_TO_READ) {
queue.remove();
}
queue.add(scanner.nextLine());
}
assertEquals(OUTPUT_TO_VERIFY, String.join("\n", queue));
}
}
5.使用NIO2 Files
如果我們想處理大文件,我們可以使用Files類別.它的Lines方法提供了一個流來逐行讀取檔案。之後,我們將使用類似Queue方式來讀取所需的內容:
@Test
public void givenLargeFile_whenUsingFilesAPI_thenExtractedLastLinesCorrect() throws IOException{
try (Stream<String> lines = Files.lines(Paths.get(FILE_PATH))) {
Queue<String> queue = new LinkedList<>();
lines.forEach(line -> {
if (queue.size() >= LAST_LINES_TO_READ) {
queue.remove();
}
queue.add(line);
});
assertEquals(OUTPUT_TO_VERIFY, String.join("\n", queue));
}
}
6. 使用 Apache Commons IO
我們可以使用 Apache Commons IO 函式庫。我們將使用FileUtils類別和ReversedLinesFileReader class.
6.1.使用FileUtils類別讀取文件
此類別提供了readLines方法,使用該方法我們可以讀取清單中的整個檔案。這會導致整個文件內容儲存在記憶體中。我們可以遍歷列表,可以讀取到需要的內容:
@Test
public void givenFile_whenUsingFileUtils_thenExtractedLastLinesCorrect() throws IOException{
File file = new File(FILE_PATH);
List<String> lines = FileUtils.readLines(file, "UTF-8");
StringBuilder stringBuilder = new StringBuilder();
for (int i = (lines.size() - LAST_LINES_TO_READ); i < lines.size(); i++) {
stringBuilder.append(lines.get(i)).append("\n");
}
assertEquals(OUTPUT_TO_VERIFY, stringBuilder.toString().trim());
}
6.2.使用ReversedLinesFileReader類別讀取文件
此類別允許使用其readLines方法以相反的順序讀取檔案。這有助於直接從最後讀取所需的內容,而無需應用任何其他邏輯或跳過文件內容:
@Test
public void givenFile_whenUsingReverseFileReader_thenExtractedLastLinesCorrect() throws IOException{
File file = new File(FILE_PATH);
try (ReversedLinesFileReader rlfReader = new ReversedLinesFileReader(file, StandardCharsets.UTF_8)) {
List<String> lastLines = rlfReader.readLines(LAST_LINES_TO_READ);
StringBuilder stringBuilder = new StringBuilder();
Collections.reverse(lastLines);
lastLines.forEach(
line -> stringBuilder.append(line).append("\n")
);
assertEquals(OUTPUT_TO_VERIFY, stringBuilder.toString().trim());
}
}
七、結論
在本文中,我們研究了從文件中讀取最後 N 行的不同方法。我們應該考慮應用程式是否可以承受更多的 CPU 使用率或更多的記憶體使用率來選擇方法。
本文中的所有程式碼都可以在 GitHub 上取得。
本作品係原創或者翻譯,採用《署名-非商業性使用-禁止演繹4.0國際》許可協議