簡體   English   中英

如何僅讀取 Java 中 csv 文件的最后一行?

[英]How do I read only the last line of a csv file in Java?

我有一個 csv 文件,它的行數並不總是相同。 但是,我想要一種只讀取最后一行的方法,這樣我就可以訪問最后一行的第一列。 到目前為止,我還沒有找到解決方案,正是這樣做的。

現在我正處於我會用 BufferedReader 讀取每一行並將其保存到數組中的點上。

public void readPreviousEntryID(){
    String path = "csvs/cartEntries.csv";
    try {
        BufferedReader br = new BufferedReader((new FileReader(path)));
        String line;
        while ((line = br.readLine() != null)) {
            String[] values = line.split(",");
        }
    } catch (FileNotFoundException e) {
        throw new RuntimeException(e);
    }
}

通常我會使用 values[0] 訪問每一行的第一個條目。 但我只想要最后一行的第一個值。

我想過通過增加 integer 然后使用 integer 的最終值來訪問相應的行來計算 while 循環中的行數,但我不確定這是否可行或我將如何實現它。

我希望我包含了足夠的信息以使問題易於理解。 這是我在這里的第一個問題,我對 Java 很陌生。

只需循環讀取文件的行並保存讀取的最后一行的values 循環終止后, values包含文件中最后一行的內容。

public void readPreviousEntryID() throws IOException {
    String path = "csvs/cartEntries.csv";
    try (FileReader fr = new FileReader(path);
         BufferedReader br = new BufferedReader(fr)) {
        String[] values = null;
        String line = br.readLine();
        while (line != null) {
            values = line.split(",");
            line = br.readLine();
        }
        if (values == null) {
            throw new IOException("File is empty.");
        }
        // Handle 'values[0]'
    }
}

上述代碼的優點是不需要將整個文件內容存儲在計算機 memory 中。 如果 CSV 文件非常大,您可能會得到OutOfMemoryError

請注意,在閱讀完文件后關閉文件很重要。 從 Java 7 開始,您可以使用try-with-resources

與其捕獲IOException並將其包裝在RuntimeException中,我建議您簡單地聲明方法readPreviousEntryID可能會拋出IOException 請參閱未經檢查的異常 - 爭議

在循環終止后檢查values是否包含預期的元素數量可能也是一個好主意,例如

if (values.length == 5) {
    // Handle 'values[0]'
}
else {
    throw new IOException("Invalid last line.");
}

編輯

或者,無需拆分每一行。 只需保存最后一行讀取並在循環終止后拆分最后一行。

public void readPreviousEntryID() throws IOException {
    String path = "csvs/cartEntries.csv";
    try (FileReader fr = new FileReader(path);
         BufferedReader br = new BufferedReader(fr)) {
        String lastLine = null;
        String line = br.readLine();
        while (line != null) {
            lastLine = line;
            line = br.readLine();
        }
        if (lastLine == null) {
            throw new IOException("File is empty.");
        }
        String[] values = lastLine.split(",");
        // Handle 'values[0]'
    }
}

為什么不將所有行存儲到 List 並獲取最后一行詳細信息,如下所示

private List<String[]> readLines = new ArrayList<>();
    
public void readPreviousEntryID(){
    String path = "csvs/cartEntries.csv";
    try {
        String line;
        BufferedReader br = new BufferedReader(new FileReader(path));
        while ((line = br.readLine()) != null) {
            String[] values = line.split(",");
            readLines.add(values);
        }
        br.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public String[] getLastLine() {
    return readLines.get(readLines.size()-1);
}

上面的 function 將給出 csv 文件的最后一行。

在 Linux 中,可以使用tail命令打印最后n行。 搜索java tail會得到一些實現。

大文件的一個很好的快速實現將使用 RandomAccessFile,可能是 MemoryMappedByteBuffer,然后從末尾搜索\n

在您的情況下,您可以保持簡單。

public String readPreviousEntryID(){
    Path path = Paths.get("csvs/cartEntries.csv");
    try (Stream<String> lines = Files.lines(path, Charset.defaultCharset())) {
        return lines
                   .filter(line -> !line.isEmpty())
                   .reduce("", (acc, line) -> line);
    } catch (FileNotFoundException e) {
        // You gave a relative path, show the actual full path:
        System.out.println("File not found: " + Files.toAbsolutePath());
        throw new RuntimeException(e);
    } // Automatically closes the Stream lines, even on exception or return.
}
  • Try-with-resources try (... declarations of AutoCloseables...) {... }確保調用.close()
  • Stream ,最新的遍歷項目。 這里跳過空行並“累積”最后一行。 您無需保留 memory 中的所有行。
  • Lambdas , x ->...(x, y) ->...分別聲明一個匿名 function 。 2個參數聲明。
  • Path是僅磁盤文件File的概括。 路徑也可以來自 URL、zip 文件等。
  • Files是一個有價值的實用程序 class 提供許多與Path相關的好東西。 Files .

已經發布了一些好的答案。 這是使用流的變體。

此外,了解 NIO.2 作為使用 Java 中文件的現代方式。

一些未經測試的代碼嘗試:

Path path = Paths.get( "/csvs" , "cartEntries.csv" ) ;
Optional < String > lastLine = 
    Files
        .lines( path )
        .reduce( ( previousLine , currentLine ) -> currentLine ) ;
if( lastLine.isPresent() ) {
    String[] parts = lastLine.get().split( "," ) ;
    …
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM