Java:尝试从一个非常大的文件中读取对象时出现了内存溢出异常。

huangapple 未分类评论54阅读模式
英文:

Java: OutOfMemory exception when trying to read objects from a very large file

问题

以下是您要求的翻译部分:

我已经使用下面的代码将近10,000个对象保存在文件中:

boolean exists = Tools.getDeviceInfo().exists();
FileOutputStream fos = new FileOutputStream(Tools.getDeviceInfo(), true);
ObjectOutputStream oos = exists ?
    new ObjectOutputStream(fos) {
        protected void writeStreamHeader() throws IOException {
            reset();
        }
    } : new ObjectOutputStream(fos);
oos.writeObject(deviceInfos);

现在,当我尝试读取文件时,会抛出内存不足异常。我该如何解决这个问题。以下是读取对象的代码:

FileInputStream fis = new FileInputStream(Tools.getDeviceInfo());
ObjectInputStream ois = new ObjectInputStream(fis);
ArrayList<DeviceInfo> arrayList = new ArrayList<>();
try {
    arrayList.addAll((ArrayList<DeviceInfo>) ois.readObject());
} catch (Exception e) {
    e.printStackTrace();
}
ois.close();
return arrayList;

我之所以想要读取所有对象,是因为我想在表格视图中显示所有数据,所以我需要将所有(10,000行)添加到数组列表中并显示在表格视图中。
是否有任何选项可以限制readObject()方法,以便它只能从非常大的文件中检索出少量对象。
我该如何改进这个?请帮忙指导。

英文:

I have saved almost 10k objects in a file using this code below:

boolean exists = Tools.getDeviceInfo().exists();
        FileOutputStream fos = new FileOutputStream(Tools.getDeviceInfo(), true);
        ObjectOutputStream oos = exists ?
                new ObjectOutputStream(fos) {
                    protected void writeStreamHeader() throws IOException {
                        reset();
                    }
                }:new ObjectOutputStream(fos);
        oos.writeObject(deviceInfos);

Now when I'm trying to read the file it is throwing OutOfMemory exception. How I can resolve this. Below is the code for reading objects.

FileInputStream fis = new FileInputStream(Tools.getDeviceInfo());
        ObjectInputStream ois = new ObjectInputStream(fis);
        ArrayList&lt;DeviceInfo&gt; arrayList = new ArrayList&lt;&gt;();
        try {
            arrayList.addAll((ArrayList&lt;DeviceInfo&gt;)ois.readObject());
        } catch (Exception e) {
            e.printStackTrace();
        }
        ois.close();
        return arrayList;

The reason i want to read all objects is I want to show all the data in tableview so i need to add all the (10k rows) into arraylist and show it on tableview.
Is there any option to limit the readObject(), so it can only retrieve few objects from a very large file.
How I can improve this? Please help.

答案1

得分: 0

你正在一次性对整个集合进行序列化和反序列化。如果你写入各个对象(而不是包含的 ArrayList),就能够一次性读取一个范围。

英文:

You're serializing and deserializing the entire collection in one go. If you write the individual objects (rather than the containing ArrayList) you'd be able to read a range at a time.

答案2

得分: 0

你在这里的情况有些棘手。

看起来你已经将所有的对象放入一个列表中,然后使用单个writeObject调用将该列表保存到文件中。

如果你这样做,那么你实际上没有其他选择,只能将整个列表读回来。我猜,或许你可以实现一个“hack”(使用自定义的读取对象方法或类似方法)将不需要的DeviceInfo对象“读取”为null以节省空间。但这可能会带来一些不利影响。

一个解决方案是通过逐个序列化元素来序列化原始列表。然后你可以逐个读取它们,忽略掉你不想要的部分。虽然这并不高效,但你应该能够避免用那些当前不需要的对象填充堆内存。

一个更好的解决方案是使用另一种保存数据的方法:

  • 你可以使用关系型数据库(RDBMS)、NoSQL数据库或者类似BerkleyDB的平面文件数据库,然后只选择你想要显示的行。

  • 你可以使用另一种序列化格式,比如JSON、XML或CSV,它们具有流式API。然后你可以流式地读取整个文件,只实例化你想要显示的元素。

某种类型的数据库可能是更好的选择。

英文:

You are kind of stuffed here.

It looks like you have put all of the objects into a list and then saved the list to the file using a single writeObject call.

If you do that, you don't have any real choice but to read back the entire list. I guess, conceivably, you could implement a hack (with custom read object methods or similar) to "read" the unwanted DeviceInfo objects as null to save space. But that is liable to have down-sides.

One solution is to serialize the original list by serializing the elements individually. Then you can read them back one at a time, and ignore the ones that you don't want. It is not efficient, but you should be able to avoid filling the heap with objects that are not currently needed.

A better solution would be to use another method of saving the data:

  • You could use an RDBMS, a NoSQL database or a flat-file database (like BerkleyDB) and select just the rows that you want to display.

  • You could use another serialization format such as JSON, XML or CSV which has a streaming API. Then you stream the entire file and only reify the elements you want to display.

A database of some kind would be preferable.

答案3

得分: -1

为了从文件中读取10,000个对象,请尝试使用java.util.scanner。

FileInputStream fInputStream = null;
Scanner scanner = null;
try {
    fInputStream = new FileInputStream(path);//file path
    scanner = new Scanner(fInputStream, "UTF-8");
    ArrayList<DeviceInfo> arrayList = new ArrayList<>();
    while (scanner.hasNextLine()) {
        DeviceInfo dObj = new DeviceInfo();
        dObj = scanner.nextLine();
        arrayList.addall(dObj);
    }
    // 注意,Scanner会压制内存不足异常
    if (scanner.ioException() != null) {
        throw scanner.ioException();
    }
} finally {
    if (fInputStream != null) {
        fInputStream.close();
    }
    if (scanner != null) {
        scanner.close();
    }
}

以上代码将帮助在不用迭代方式、不耗尽可用内存的情况下处理一个大文件中的行(每行一个对象)。

英文:

In order to read 10k objects from a file please try to use java.util.scanner

FileInputStream fInputStream = null;
	Scanner scanner = null;
	try {
	    fInputStream = new FileInputStream(path);//file path
	    scanner = new Scanner(fInputStream, &quot;UTF-8&quot;);
		 ArrayList&lt;DeviceInfo&gt; arrayList = new ArrayList&lt;&gt;();
	    while (scanner.hasNextLine()) {
	    DeviceInfo dObj = new DeviceInfo();
	    dObj = scanner.nextLine();
		arrayList.addall(dObj);
	    }
	    // note that Scanner suppresses out of memory exception
	    if (scanner.ioException() != null) {
	        throw scanner.ioException();
	    }
	} finally {
	    if (fInputStream != null) {
	    	fInputStream.close();
	    }
	    if (scanner != null) {
	        scanner.close();
	    }
    	}

The above code will help to process lines(one object each line) in a large file without iteratively, without exhausting the available memory.

huangapple
  • 本文由 发表于 2020年3月15日 16:38:18
  • 转载请务必保留本文链接:https://java.coder-hub.com/60691058.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定