Java – 按块读取文本文件

我想读取不同块的日志文件,使其成为multithreading。 该应用程序将在具有多个硬盘的服务器端环境中运行。 在阅读了块之后,应用程序将逐行处理每个块的行。

我已经使用bufferedreader完成了每个文件行的读取,我可以使用RandomAccessFile和MappedByteBuffer组合我的文件块,但是将这两者结合起来并不容易。

问题是,块正在切入我的块的最后一行。 我从来没有我的块的最后一行,所以处理这个最后的日志是不可能的。 我正试图找到一种方法将我的文件剪切成可变长度的块,尊重行的结尾。

有没有人有这样做的代码?

在开始处理块之前,您可以在文件中找到位于行边界的偏移量。 通过将文件大小除以块数来开始偏移,并搜索直到找到行边界。 然后将这些偏移量提供给multithreading文件处理器。 这是一个完整的示例,它使用可用处理器的数量来计算块数:

import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ReadFileByChunks { public static void main(String[] args) throws IOException { int chunks = Runtime.getRuntime().availableProcessors(); long[] offsets = new long[chunks]; File file = new File("your.file"); // determine line boundaries for number of chunks RandomAccessFile raf = new RandomAccessFile(file, "r"); for (int i = 1; i < chunks; i++) { raf.seek(i * file.length() / chunks); while (true) { int read = raf.read(); if (read == '\n' || read == -1) { break; } } offsets[i] = raf.getFilePointer(); } raf.close(); // process each chunk using a thread for each one ExecutorService service = Executors.newFixedThreadPool(chunks); for (int i = 0; i < chunks; i++) { long start = offsets[i]; long end = i < chunks - 1 ? offsets[i + 1] : file.length(); service.execute(new FileProcessor(file, start, end)); } service.shutdown(); } static class FileProcessor implements Runnable { private final File file; private final long start; private final long end; public FileProcessor(File file, long start, long end) { this.file = file; this.start = start; this.end = end; } public void run() { try { RandomAccessFile raf = new RandomAccessFile(file, "r"); raf.seek(start); while (raf.getFilePointer() < end) { String line = raf.readLine(); if (line == null) { continue; } // do what you need per line here System.out.println(line); } raf.close(); } catch (IOException e) { // deal with exception } } } } 

你需要让你的块重叠。 如果没有行比块长,那么一个块重叠就足够了。 您确定需要multithreading版本吗? gnu grep的表现不够好吗?

gnu grep的实现解决了跨越块边界的线的问题。 如果您不熟悉GNU许可证,您可以从那里借用想法和代码。 这是一个非常有效的单线程实现。