当前位置: 首页 > 面试题库 >

在Java中读取大文件时如何避免OutOfMemory异常

顾梓
2023-03-14
问题内容

我正在研究从文件读取大量数据的应用程序。基本上,我有一个巨大的文件(大约1.5-2个演出),其中包含不同的对象(每个文件约5至1000万个对象)。我需要阅读所有内容,并将其放置在应用程序中的不同地图上。问题是该应用程序在某些时候读取对象时内存不足。仅当我将其设置为使用-
Xmx4096m时,它才能处理该文件。但是,如果文件更大,它将无法再执行此操作。

这是代码片段:

String sampleFileName = "sample.file";
FileInputStream fileInputStream = null;
ObjectInputStream objectInputStream = null;
try{
    fileInputStream = new FileInputStream(new File(sampleFileName));
    int bufferSize = 16 * 1024;
    objectInputStream = new ObjectInputStream(new BufferedInputStream(fileInputStream, bufferSize));
        while (true){
            try{
                Object objectToRead = objectInputStream.readUnshared();
                if (objectToRead == null){
                    break;
                }
                // doing something with the object
            }catch (EOFException eofe){
                eofe.printStackTrace();
                break;
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
} catch (Exception e){
        e.printStackTrace();
}finally{
    if (objectInputStream != null){
        try{
            objectInputStream.close();
        }catch (Exception e2){
            e2.printStackTrace();
        }
    }
    if (fileInputStream != null){
        try{
            fileInputStream.close();
        }catch (Exception e2){
            e2.printStackTrace();
        }
    }
}

首先,我使用的是 objectInputStream.readObject() 而不是
objectInputStream.readUnshared()
,因此它部分解决了该问题。当我将内存从2048增加到4096时,它开始解析文件。BufferedInputStream已在使用中。在网络上,我仅找到了如何读取行或字节的示例,但是从性能角度来看,没有任何关于对象的示例。

如何在不增加JVM内存和避免OutOfMemory异常的情况下读取文件?有什么方法可以从文件中读取对象,而不在内存中保留任何其他内容?


问题答案:

在读取大文件,解析对象并将其保留在内存中时,有几种解决方案需要权衡取舍:

  1. 您可以将所有已解析的对象放入部署在一台服务器上的该应用程序的内存中。它要么要求以非常压缩的方式存储所有对象,例如使用字节或整数存储2个数字,要么使用其他数据结构中的某种形式的移位。换句话说,将所有对象放入可能的最小空间中。或增加该服务器的内存(垂直扩展)

a)但是,读取文件可能会占用太多内存,因此您必须分块读取它们。例如,这就是我在处理json文件的方法:

    JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8"));
    if (reader.hasNext()) {
        reader.beginObject();
        String name = reader.nextName();

        if ("content".equals(name)) {
            reader.beginArray();

            parseContentJsonArray(reader, name2ContentMap);

            reader.endArray();
        }
        name = reader.nextName();
        if ("ad".equals(name)) {
            reader.beginArray();

            parsePrerollJsonArray(reader, prerollMap);

            reader.endArray();
        }
    }

这个想法是要有一种方法来识别某些对象的开始和结束时间,并仅读取该部分。

b)如果可以的话,您也可以在源头将文件拆分为较小的文件,这样将更易于阅读。

  1. 您无法在一台服务器上容纳该应用程序的所有解析对象。在这种情况下,您必须基于某些对象属性进行分片。例如,将基于美国州的数据拆分为多个服务器。

希望它对您的解决方案有所帮助。



 类似资料:
  • 问题内容: 我可以在不生成编译的.pyc文件的情况下运行python解释器吗? 问题答案: 来自“ Python 2.6的新增功能- 解释器更改” : 现在,可以通过向Python解释器提供-B开关,或者通过在运行解释器之前设置 PYTHONDONTWRITEBYTECODE环境变量来阻止Python编写.pyc或.pyo文件。此设置可作为Python程序的 变量使用,并且Python代码可以更改

  • 我试图比较两个不同对象的名称,但是当使用方法将一个项目与null进行比较时,我一直得到异常。我尝试了很多方法,包括other.equals(哈哈)、haha.equals(其他)等等,但都失败了。

  • 我正在使用Java开发一个web应用程序,在这里我有一个方法可以读取。使用apache poi的xlsx文件: 该方法工作正常,但是该方法处理具有数千行记录的文件的可能性有多大,例如,大约2530万行。当处理一个大文件时,我采取以下异常: 我需要知道如何避免这种错误。例如,如果有,请读取并处理该文件。xlsx 1000至1000线,或其他解决方案。

  • 问题内容: 我需要非常了解Java和内存问题的人的建议。我有一个大文件(大约1.5GB),我需要将此文件切成许多小文件(例如100个小文件)。 我通常知道如何做到这一点(使用),但是我想知道你是否对内存有任何建议,或者提示如何更快地做到这一点。 我的文件包含文本,它不是二进制文件,每行大约有20个字符。 问题答案: 首先,如果你的文件包含二进制数据,则使用将是一个大错误(因为你会将数据转换为Str

  • 问题内容: 一旦我的代码进入我的循环,它就会生成is close异常。是什么导致此异常,我该如何纠正? 编辑: 我在代码中注意到我与另一个嵌套循环,两个结果集都来自同一数据库,这是一个问题吗? 问题答案: 听起来好像您在遍历第一个语句的结果集之前在同一连接中执行了另一个语句。如果要嵌套处理来自同一数据库的两个结果集,则说明您做错了什么。这些集合的组合应在数据库侧完成。

  • 问题内容: 在我日常的Web应用程序开发中,有许多情况需要我们从用户那里获取一些输入。 然后将这个数字输入传递给可能是应用程序的服务层或DAO层。 由于它是一个数字(整数或浮点数),在某个阶段,我们需要将其转换为整数,如以下代码片段所示。 在上述情况下,在这里,我必须检查输入是否不为null或是否没有输入(空白),或者有时是否有非数字输入的可能性,例如blah,test等。 处理此类情况的最佳方法