从磁盘读取文件与将文件加载到主内存进行处理的区别

5
如何将文件加载到主内存?
我使用以下代码读取文件:
```python ```
BufferReader buf = new BufferedReader(FileReader());

我猜这是从硬盘逐行读取文件。这样做有什么好处?
直接将文件加载到内存中的好处是什么?在Java中如何实现?
我在ScannerRandomAccessFile方法中找到了一些示例。它们是否将文件加载到内存中?我应该使用它们吗?其中两个应该使用哪个?
提前感谢!!!

2
你的分析器显示了什么? - trashgod
你认为你的堆在哪里?“将文件加载到内存中”是一个毫无意义的表达。 - Hot Licks
我没有性能分析器。我在hadoop集群上运行程序,并使用cygwin进行监控。我想要一种直接将文件加载到内存中而不是从磁盘逐行读取的方法。我认为堆是动态内存分配。除此之外,我对它没有什么概念。请帮忙! - Mahalakshmi Lakshminarayanan
你打算在“加载”文件后做什么?它有多大? - Hot Licks
我想从中读取选定的数据。我不知道文件的大小。我在Hadoop reduce类中使用它。我认为对于小数据集,文件将足够小以适合内存。我观察到从磁盘逐行读取文件使程序运行缓慢,因此我想将其加载到内存中,逐行读取并从中提取所需信息。 - Mahalakshmi Lakshminarayanan
2个回答

7
BufferReader buf = new BufferedReader(FileReader());

I presume that this is reading the file line by line from the disk. What is the advantage of this?

并不完全是这样。它是按默认缓冲区大小(我认为是8k字节)分块读取文件。
优点是您不需要一个巨大的堆来读取一个巨大的文件。这是一个重要问题,因为最大堆大小只能在JVM启动时(使用Hotspot Java)指定。
您还不会消耗系统的物理/虚拟内存资源来表示巨大的堆。
将文件直接加载到内存中的优点是什么?
它减少了系统调用的数量,并且可能会更快地读取文件。速度提升多少取决于许多因素。而且您还需要处理非常大的文件。
我们如何在Java中实现这一点?
1. 找出文件的大小。 2. 分配足够大的字节数组(或字符数组)。 3. 使用相关的read(byte[],int,int)或read(char[],int,int)方法读取整个文件。
您还可以使用内存映射文件...但那需要使用Buffer API,这可能有点棘手。
我在Scanner或RandomAccessFile方法上找到了一些示例。它们会将文件加载到内存中吗?
不会,也不会。
我应该使用它们吗?其中两者应该使用哪一个?
它们是否提供您需要的功能?您需要读取/解析基于文本的数据吗?您需要对二进制数据进行随机访问吗?
在正常情况下,您应该基于所需的功能选择I/O API,并次要考虑性能问题。如果您打算在读取时对其进行解析,则使用BufferedInputStream或BufferedReader通常足以获得可接受的性能。(但是,如果您实际上需要将整个文件以其原始形式保存在内存中,则BufferedXxx包装器类实际上会使读取变慢一些。)
注意:可接受的性能与最佳性能不同,但如果这不是明确要求,您的客户/项目经理可能不希望您浪费时间编写代码以实现最佳性能。

我需要读取和解析文件。我正在为Hadoop MapReduce程序使用它。我试图使用缓冲读取器从磁盘中读取文件。但是这似乎需要很长时间。因此,我想也许我应该将整个文件加载到内存中,这可能会提高性能。 - Mahalakshmi Lakshminarayanan
你需要对你的应用程序进行性能分析,以确定它在读取/解析过程中究竟花费了多少时间。 - Stephen C
1
请注意,如果您的意图是在不解析的情况下读取整个文件,则缓冲包装器只会向操作添加一个额外的副本。但是,如果您正在读取文件、解析文件,然后再也不引用该文件,那么您需要一个缓冲读取器,并且一次性读取整个文件可能是一个坏主意。 - Hot Licks

4

如果您正在读取文件并解析它,一次从头到尾提取您的数据,然后不再引用该文件,则缓冲读取器是您可以获得的最"优化"的选择。您可以通过调整缓冲区大小来"调整"性能--较大的缓冲区将从文件中读取更大的块。(使缓冲区成为2的幂--例如262144)。读取整个大文件(大于1mb)通常会在页面和堆管理方面影响性能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接