编辑:
我最终使用FileInputStream仅将索引保存到我感兴趣的位置,而不是将文件加载到内存(在需要时更新位置)。
如果您保存更多数据,如果每次保留较少数据或更多内存(较少内存访问),则可配置为使用较少内存(更多内存访问)。
您可以使用响应时间调整缓冲区,假设您正在循环访问某些代码。
虽然我确信使用非阻塞I \ O可以改善这一点,但我没有发现它直观,而且我已经使用了我可以轻松控制的简单事物。
我有一个大学的项目,涉及比较字节序列的大文件。
为了快速完成这项工作,我决定将所有文件加载到内存中(文件大约总共500mb)并比较它们,同时将信息存储在一个小的db中提取(通常不进行查询)。
我已经将“File”类扩展为一个新类“MappedFile”,其中每个Mappedfile都有一个字节数组(在构造时创建),保存文件的字节。
这是整个MemFile类:
public class MemFile extends File{
private String md5;
private byte[] bytes;
public MemFile(String pathname) {
super(pathname);
}
public byte[] getBytes(){
if (this.bytes == null){
this.bytes = FileUtils.getFileBytes(this);
}
return this.bytes;
}
public String getMD5(){
if (this.md5 == null){
this.md5 = MD5Generator.generate(this.getAbsolutePath());
}
return this.md5;
}
}
我拿着一个列表,我从大字节数组中提取较小的数组,然后在其他文件中查找它们。
我的问题是,当我只使用500mb文件的一小部分时,我的内存耗尽(我开始使用2GB的内存进行eclipse)
这是一种现实的方法来完成这项工作还是我将很多东西加载到内存中?
是否有以某种方式监控虚拟内存的选项?
答案 0 :(得分:2)
我会使用内存映射文件。这些不占用大量内存,加载速度更快。他们只使用虚拟内存,只要你有64位就可以加载数千个这么多问题。
FileChannel fc = new FileInputStream(fileName).getChannel();
MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
您可以继续为所有文件执行此操作,并且它将仅使用几KB的堆。注意:此工作适用于最大2 GB的文件(大于您必须分批映射的文件)
答案 1 :(得分:2)
JDK已经拥有了你想要的东西:FileChannel#map()
。
此外,它会返回MappedByteBuffer
,其扩展为ByteBuffer
,您可以使用.equals()
来比较内容。
使用Java 7,它就像:
一样简单final FileChannel fc = FileChannel.open(Paths.get("/path/to/file"),
StandardOpenOption.READ);
final ByteBuffer buf = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
(哦,它实现Closeable
,因此AutoCloseable
)