从内存而不是磁盘读取文件

时间:2014-06-06 05:12:20

标签: java xml caching java-io

我有一个Java项目,其中包含大量XML文件(> 500)。在运行时读取这些文件会导致性能问题。

是否可以选择将所有XML文件加载到RAM并从那里读取而不是磁盘?

我知道有像RamDisk这样的产品,但这个是商业工具。

我可以使用任何现有的Java API /库将XML文件复制到主内存并从主内存中读取吗?

8 个答案:

答案 0 :(得分:5)

我首先尝试内存映射文件,由标准java库中的RandomAccessFileFileChannel提供。通过这种方式,操作系统可以将常用的文件内容保存在内存中,从而有效地实现您的目标。

答案 1 :(得分:4)

您可以使用内存数据库来存储中间文件(XML文件)。这将提供使用ram和db的速度。

供参考使用以下链接:

  

http://www.mcobject.com/in_memory_database

在内存数据库中使用H2:

  

http://www.javatips.net/blog/2014/07/h2-in-memory-database-example

答案 2 :(得分:2)

使用 Label[] lbl ; private void setupControls() { int Totallbl = 5; int height = 30; lbl = new Label[Totallbl]; try { for (int i = 0; i < Totallbl; i++) { lbl[i] = new Label(); lbl[i].Location = new Point(20, ((i + 1) * height)); lbl[i].Name = "lbl" + i; lbl[i].Text = "LabelText"; lbl[i].AutoSize = true; this.Controls.Add(lbl[i]); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } 课程。它的行为类似于存储在文件系统中的大量字节。此类的实例支持读取和写入随机访问文件。 另外我建议使用java.io.RandomAccessFile直接从磁盘读取文件,而不是将其加载到内存中。

MemoryMappedFile

然后你可以照常阅读缓冲区。

答案 3 :(得分:0)

您是否考虑过为这些文件创建对象结构并对其进行序列化,java对象序列化和反序列化比解析XML要快得多,这再次考虑到这些500个左右的XML文件在读取之间不会被修改

here is an article讨论序列化和反序列化。

如果担心要将文件内容加载到内存中,那么考虑ByteArrayInputStreamByteArrayOutputStream类甚至可以使用ByteBuffer,这些可以将字节存储在内存中

答案 4 :(得分:0)

Java对象序列化/反序列化通常不比XML编写和解析快。当涉及大量对象时,Java序列化/反序列化实际上效率非常低,因为它跟踪每个单独的对象(因此重复的引用不会被多次序列化)。这对于对象网络非常有用,但对于简单的树结构,它会增加很多开销而没有增益。

您最好的方法可能是使用快速技术来处理XML(例如javax.xml.stream.XMLStreamReader)。除非文件很大,否则加载XML文件的时间超过30-40秒 - 您可能正在使用低效的方法来处理XML,例如将它们加载到DOM中。您还可以尝试并行读取多个文件(例如使用Java 8并行流)。

答案 5 :(得分:0)

看起来您的主要问题是大量文件,RAM不是问题。你能证实吗?

是否可以执行预处理步骤,使用某种分隔符附加所有这些文件并创建一个大文件?这样,您可以增加读取的块大小,并避免磁盘搜索的性能损失。

答案 6 :(得分:0)

您是否考虑过压缩XML文件并读取这些压缩的XML文件?压缩的XML可能只有原始或更好的3-5%。当用户可以看到它时,您可以将其解压缩,然后再次压缩存储以供进一步阅读。

这是我发现可能有用的库: zip4j

答案 7 :(得分:0)

这取决于您是否多次读取数据。

假设我们使用某种基于Java的RamDisk(它实际上是某种缓冲区或字节数组)。

进一步假设处理数据的时间少于读取数据。所以你必须至少读一次。因此,如果您首先从磁盘到内存读取它,然后从内存中处理它,那将没有任何区别。

如果您不止一次读取文件,可以将所有文件读入内存(各种选项,缓冲区,字节数组,自定义文件系统......)。

如果处理时间比读取时长(似乎不是这种情况),您可以使用单独的线程从磁盘预取文件 - 并使用另一个线程处理内存中的数据。