Zor*_*did 5 java file-io nio bytebuffer filechannel
我真的遇到了麻烦:我想用FileChannels和MappedByteBuffers 读取几GB的HUGE文件- 我发现的所有文档都暗示使用该FileChannel.map()方法映射文件相当简单.当然,限制为2GB,因为所有Buffer方法都使用int来定位,限制和容量 - 但系统隐含的限制如何呢?
实际上,我遇到很多关于OutOfMemoryExceptions 的问题!并没有真正定义限制的文档!那么 - 如何将一个符合int-limit的文件安全地映射到一个或几个MappedByteBuffers而不仅仅是异常?
在尝试之前,我可以问系统我可以安全地映射文件的哪个部分FileChannel.map()?怎么样?为什么关于这个功能的文档很少?
我可以提供一些工作代码.这是否能解决您的问题很难说.这通过一个文件来搜索被识别的模式Hunter.
请参阅优秀的文章Java技巧:如何快速阅读原始研究的文件(不是我的).
// 4k buffer size.
static final int SIZE = 4 * 1024;
static byte[] buffer = new byte[SIZE];
// Fastest because a FileInputStream has an associated channel.
private static void ScanDataFile(Hunter p, FileInputStream f) throws FileNotFoundException, IOException {
// Use a mapped and buffered stream for best speed.
// See: http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly
FileChannel ch = f.getChannel();
long red = 0L;
do {
long read = Math.min(Integer.MAX_VALUE, ch.size() - red);
MappedByteBuffer mb = ch.map(FileChannel.MapMode.READ_ONLY, red, read);
int nGet;
while (mb.hasRemaining() && p.ok()) {
nGet = Math.min(mb.remaining(), SIZE);
mb.get(buffer, 0, nGet);
for (int i = 0; i < nGet && p.ok(); i++) {
p.check(buffer[i]);
}
}
red += read;
} while (red < ch.size() && p.ok());
// Finish off.
p.close();
ch.close();
f.close();
}
Run Code Online (Sandbox Code Playgroud)
我使用的是List<ByteBuffer>每个ByteBuffer以16 MB到1 GB的块映射到文件的位置.我使用2的幂来简化逻辑.我用它来映射最高8 TB的文件.
内存映射文件的一个关键限制是您受虚拟内存的限制.如果你有一个32位的JVM,你将无法进行非常多的映射.
我不会继续为文件创建新的内存映射,因为它们永远不会被清除.你可以创建很多这些,但在某些系统上似乎有大约32K的限制(无论它们有多小)
我发现MemoryMappedFiles有用的主要原因是它们不需要刷新(如果你可以假设操作系统不会死)这允许你以低延迟的方式写入数据,而不必担心如果丢失过多的数据应用程序因必须write()或flush()而死亡或性能过高.
文件越大,您就越不希望将其全部存储在内存中。设计一种方法来一次处理一个缓冲区、一次处理一行等。
MappedByteBuffers 尤其有问题,因为没有定义映射内存的释放,因此一次使用多个内存基本上肯定会失败。
| 归档时间: |
|
| 查看次数: |
6742 次 |
| 最近记录: |