簡體   English   中英

Java中的文本文件解析

[英]Text File Parsing in Java

我正在使用FileInputStream讀取文本文件,該文件將文件內容放入一個字節數組中。 然后我使用 new String(byte) 將字節數組轉換為字符串。

一旦我有了字符串,我就使用String.split("\\n")將文件拆分為一個字符串數組,然后將該字符串數組取出並通過執行String.split(",")解析它並保存內容在一個數組列表中。

我有一個200MB 以上的文件,當我用 1GB 的內存啟動 JVM 時,它的內存不足。 我知道我必須在某個地方正確地做某事,我只是不確定我解析的方式或我使用的數據結構是否不正確。

解析文件也需要我大約 12 秒,這似乎需要很多時間。 任何人都可以指出我可能正在做的導致我內存不足的事情以及可能導致我的程序運行緩慢的原因嗎?

文件內容如下圖所示:

"12334", "100", "1.233", "TEST", "TEXT", "1234"
"12334", "100", "1.233", "TEST", "TEXT", "1234"
.
.
.
"12334", "100", "1.233", "TEST", "TEXT", "1234"

謝謝

我不確定它在內存方面的效率如何,但我的第一種方法是使用Scanner,因為它非常容易使用:

File file = new File("/path/to/my/file.txt");
Scanner input = new Scanner(file);

while(input.hasNext()) {
    String nextToken = input.next();
    //or to process line by line
    String nextLine = input.nextLine();
}

input.close();

檢查 API 以了解如何更改用於拆分令牌的分隔符。

聽起來你對我做錯了 - 一個完整的對象創建正在進行中。

該“測試”文件的代表性如何? 你真的用這些數據做什么? 如果這是您真正擁有的典型數據,我會說該數據中有很多重復。

如果無論如何都將在字符串中,請從 BufferedReader 開始讀取每一行。 將該列表預先分配到接近您需要的大小,這樣您就不會浪費每次添加到它的資源。 在逗號處拆分每一行; 一定要去掉雙引號。

您可能會問自己:“為什么我需要一次性將整個文件保存在內存中?” 你能讀一點,處理一點,而且永遠不會一次把整個事情都記在記憶里嗎? 只有您足夠了解您的問題才能回答。

如果您有 JDK 6,也許您可​​以啟動 jvisualvm 並查看內存發生了什么。 那將是一個很好的線索。

看看這些頁面。 它們包含許多開源 CSV 解析器。 JSaPar就是其中之一。

聽起來您目前在內存中擁有整個文件的 3 個副本:字節數組、字符串和行數組。

與其將字節讀入字節數組,然后使用new String()轉換為字符,不如使用 InputStreamReader,它會逐步轉換為字符,而不是預先全部轉換為字符。

此外,不應使用 String.split("\\n") 來獲取各行,而應一次讀取一行。 您可以在BufferedReader使用readLine()方法。

嘗試這樣的事情:

BufferedReader reader = new BufferedReader(new InputStreamReader(fileInputStream, "UTF-8"));
try {
  while (true) {
    String line = reader.readLine();
    if (line == null) break;
    String[] fields = line.split(",");
    // process fields here
  }
} finally {
  reader.close();
}

如果您有一個 200,000,000 個字符的文件並每五個字符拆分一次,那么您將擁有 40,000,000 個String對象。 假設他們與原始 400 MB Stringchar是 2 個字節)共享實際字符數據。 一個String是 32 個字節,所以是 1,280,000,000 個字節的String對象。

(可能值得注意的是,這非常依賴於實現split可以創建具有全新支持char[]完全字符串,或者,OTOH,共享一些常見的String值。一些 Java 實現不使用char[]的切片。有些可能會使用類似於 UTF-8 的緊湊形式,並且隨機訪問時間很短。)

即使假設更長的字符串,那也是很多對象。 有了這么多數據,您可能希望像原始數據一樣以緊湊的形式處理其中的大部分(僅使用索引)。 僅轉換為您需要的對象。 實現應該像數據庫一樣(盡管它們傳統上不能有效地處理可變長度的字符串)。

在調用/調用您的程序時,您可以使用以下命令:java [-options] className [args...]
代替 [-options] 提供更多內存,例如 -Xmx1024m 或更多。 但這只是一種解決方法,您必須更改解析機制。

暫無
暫無

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

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