首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >安卓:文件读取- OutOfMemory问题

安卓:文件读取- OutOfMemory问题
EN

Stack Overflow用户
提问于 2013-02-08 08:20:33
回答 3查看 1.5K关注 0票数 1

我正在创建一个需要从文件中读取数据的应用程序。该文件相对较大(1.8 MB),并且是从onCreate中的异步线程读取的。当应用程序第一次启动时,它加载得很好。但是,如果您单击“后退”按钮,然后再次加载它,它就会耗尽内存并崩溃(抛出OutOfMemory错误)。

如何让它使用尽可能低的内存量和/或在完成后释放该内存?

文件读取代码(在async类的doInBackground()方法中执行):

代码语言:javascript
复制
public ArrayList<String> createDataList() {
    dataList = new ArrayList<String>();
    BufferedReader br = null;
    try {
        br = new BufferedReader(new InputStreamReader(getAssets().open(
                    "text.txt")));
        String data;
        while ((data = br.readLine()) != null) {
            dataList.add(data);
        }                           
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            br.close(); // stop reading
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    return dataList;
}

编辑*异步类:

代码语言:javascript
复制
private class loadData extends AsyncTask<Void, Void, ArrayList<String>> {

    @Override
    protected ArrayList<String> doInBackground(Void... arg0) {
        dataList = createDataList();
        return dataList;
    }

    protected void onPostExecute(ArrayList<String> result) {
        super.onPostExecute(result);
        // display first element in ArrayList in TextView as a test

    }

}

我试着根据我想要组织数据的方式来拆分文件,并将每个文本文件中的数据存储到一个单独的ArrayList中,但我在这方面也遇到了内存问题。我还将所有数据存储到一个“主”ArrayList中,然后调用该“主”上的一个方法将数据添加到适当的ArrayList中(复制“主”后立即从“主”中删除/清除数据)。

有关于如何简化和减少内存影响的想法吗?

编辑**

Logcat:

这是在您单击back按钮,然后再次加载活动时发生的。以下只是生成的一条消息(详细):

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-02-08 10:04:47

首先,确保内存中没有数据的两个副本。在开始创建新的ArrayList之前,您可以清空对旧的ArrayList.clear()的引用,尽管您必须小心地这样做--首先调用ArrayList.clear()会更彻底。

其次,使用hprof或Eclipse MAT等工具计算出ArrayList占用了多少内存。如果它使用大量的空间,您可能想要考虑更紧凑的数据表示。

所以..。从代码片段中可以看出,您只是在使用字节到字符的转换从文件中读取一串文本字符串。如果源材料是普通的UTF-8 (即本质上是ASCII码),那么您将得到UTF-16的2倍扩展,加上用于保存它的char[]对象的分配,加上包装它的String对象的大小,再加上ArrayList中条目的开销。根据文件中平均字符串的长度,这在1.8MB上可能是一个显着的倍数。

避免这种情况的一种方法是将文件作为byte[]读取到内存中,扫描它以确定每个字符串的起始位置,并只保留一个整数数组,其中包含每个字符串的起始偏移量。当您需要字符串N时,将其从byte[]解码为String并返回。这极大地减少了您的开销。您可以通过不加载文件并根据需要读出单个字符串(使用RandomAccessFile)来进一步减少它,但这可能会减慢速度。

票数 0
EN

Stack Overflow用户

发布于 2013-02-08 08:35:16

您可以尝试在清单中添加android:largeHeap="true",但Android API-8不支持它。据我所知,您正在读取数据并将其存储到堆内存中,堆内存通常非常有限,其大小取决于运行应用程序的设备。

您可能还希望在此处进行调查:android - out of memory

票数 1
EN

Stack Overflow用户

发布于 2013-02-08 10:59:16

看起来你可能在使用immutability of Strings时遇到了一点麻烦。

你为什么不试着改变你的代码,比如你可以使用StringBuilder呢?当然,您必须更改多个内容,但它与您的代码足够相似,并且不会很快填满您的内存。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14763656

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档