簡體   English   中英

使用Java 8處理和拆分大文件

[英]Processing and splitting large files with Java 8

我是Java 8的新手,我剛開始使用NIO包進行文件處理。 我需要幫助處理大型文件 - 每個文件從100,000行到1,000,000行 - 通過將每行轉換為特定格式並將格式化的行寫入新文件。 生成的新文件每個文件最多只能包含100,000行。 所以:

  • 如果我有一個500,000行的文件進行處理,我必須轉換這些行並在5個新文件上分發和打印它們。
  • 如果我有一個745,000行的文件進行處理,我必須轉換這些行並在8個新文件上打印它們。

我很難找到一種能夠有效利用Java 8新功能的方法。我已經開始根據大文件的行數確定要生成的新文件的數量,然后創建那些新的空文件:

Path largFile = Path.get("path\to\file");
long recordCount = Files.lines(file).count();
int maxRecordOfNewFiles = 100000;
int numberOfNewFiles =  1;
if (recordCount > maxRecordOfNewFiles) {
    numberOfNewFiles = Math.toIntExact(recordCount / maxRecordOfNewFiles);
if (Math.toIntExact(recordCount % maxRecordOfNewFiles) > 0) {
    numberOfNewFiles ++;
}
}

IntStream.rangeClosed(1, numberOfNewFiles).forEach((i) 
    -> {
        try {
            Path newFile = Paths.get("path\to\newFiles\newFile1.txt");
                        Files.createFile(cdpFile);
         } catch (IOException iOex) {
         }
        });

但是,當我經過的線路largeFile通過Files.lines(largeFile).forEach(())的能力,我迷路了有關如何使用格式化第一100,000行,然后確定第一個新的文件,並進行將它們打印在該文件上,然后將第二批100,000打印到第二個新文件,依此類推。

任何幫助將不勝感激。 :)

當您開始構思批處理時,我認為您應該考慮使用專門的框架。 你可能想要處理重啟,調度...... Spring Batch非常適合你並且已經提供了你想要的東西: MultiResourceItemWriter寫入多個文件,每個文件有最大行數, FlatFileItemReader用於從文件中讀取數據。


在這種情況下,您想要的是循環輸入文件的每一行,並在多個輸出文件中寫入每行的轉換。

一種方法是在輸入文件的行上創建一個Stream,映射每一行並將其發送到自定義編寫器。 當自定義編寫器達到每個文件的最大行數時,它將實現切換編寫器的邏輯。

在以下代碼中, MyWriterBufferedWriter打開到文件中。 當達到maxLines (它的倍數)時,將關閉此maxLines器並打開另一個,增加currentFile 這樣,我們寫入多個文件對讀者來說是透明的。

public static void main(String[] args) throws IOException {
    try (
        MyWriter writer = new MyWriter(10);
        Stream<String> lines = Files.lines(Paths.get("path/to/file"));
    ) {
        lines.map(l -> /* do transformation here */ l).forEach(writer::write);
    }
}

private static class MyWriter implements AutoCloseable {

    private long count = 0, currentFile = 1, maxLines = 0;
    private BufferedWriter bw = null;

    public MyWriter(long maxLines) {
        this.maxLines = maxLines;
    }

    public void write(String line) {
        try {
            if (count % maxLines == 0) {
                close();
                bw = Files.newBufferedWriter(Paths.get("path/to/newFiles/newFile" + currentFile++ + ".txt"));
            }
            bw.write(line);
            bw.newLine();
            count++;
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    @Override
    public void close() throws IOException {
        if (bw != null) bw.close();
    }
}

據我所知,有問題。 一個簡單的方法可以是:

BufferedReader buff = new BufferedReader(new FileReader(new File("H:\\Docs\\log.txt")));
Pair<Integer, BufferedWriter> ans = buff.lines().reduce(new Pair<Integer, BufferedWriter>(0, null), (count, line) -> {
    try {
        BufferedWriter w;
        if (count.getKey() % 1000 == 0) {
            if (count.getValue() != null) count.getValue().close();
            w = new BufferedWriter(new FileWriter(new File("f" + count.getKey() + ".txt")));
        } else w = count.getValue();
        w.write(line + "\n"); //do something
        return new Pair<>(count.getKey() + 1, w);
    } catch (IOException e) {
        throw new UncheckedIOException(e);
    }
}, (x, y) -> {
    throw new RuntimeException("Not supproted");
});
ans.getValue().close();

暫無
暫無

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

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