【问题标题】:Android - OutOfMemory when reading text fileAndroid - 读取文本文件时出现内存不足
【发布时间】:2011-09-18 12:32:45
【问题描述】:

我正在安卓上制作一个字典应用程序。在启动期间,应用程序将加载 .index 文件的内容(~2MB,100.000+ 行)

但是,当我使用 BufferedReader.readLine() 并对返回的字符串执行某些操作时,应用程序将导致 OutOfMemory。

// Read file snippet
Set<String> indexes = new HashSet<String)();

FileInputStream is = new FileInputStream(indexPath);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));

String readLine;

while ( (readLine = reader.readLine()) != null) {
    indexes.add(extractHeadWord(readLine));
}

// And the extractHeadWord method
private String extractHeadWord(String string) {
    String[] splitted = string.split("\\t");
    return splitted[0];
}

在阅读日志的时候发现,在执行的时候,会导致GC多次显式清理对象(GC_EXPLICIT释放了xxx个对象,其中xxx是一个很大的数字比如15000、20000)。

我尝试了另一种方法:

final int BUFFER = 50;
char[] readChar = new char[BUFFER];

//.. construct BufferedReader

while (reader.read(readChar) != -1) {
    indexes.add(new String(readChar));
    readChar = new char[BUFFER];
}

..它运行得非常快。但这并不是我想要的。

是否有任何解决方案可以像第二个 sn-p 一样快速运行并且像第一个一样易于使用?

注意。

【问题讨论】:

  • 代码sn-p中DataInputStream有什么用?看起来您不需要提取原始类型,只需要提取字符串?如果您知道Set 的大小,有时预先分配大小会很有帮助,例如new HashSet&lt;String&gt;(100000)
  • @Jeff Foster:感谢您关于分配 HashSet 大小的建议。
  • bugs.sun.com/bugdatabase/view_bug.do?bug_id=4513622 是答案所描述问题的好读物。

标签: java android dictionary io


【解决方案1】:

extractHeadWord 使用String.split 方法。此方法不会创建新字符串,而是依赖于基础字符串(在您的情况下为 line 对象)并使用索引来指出“新”字符串。

由于您对字符串的其余部分不感兴趣,因此您需要将其丢弃以便进行垃圾收集,否则整个字符串将在内存中(但您只使用其中的一部分)。

调用构造函数String(String)(“复制构造函数”)丢弃字符串的其余部分:

private String extractHeadWord(String string) {
    String[] splitted = string.split("\\t");
    return new String(splitted[0]);
}

【讨论】:

  • 是否有任何文件说明这一点?我同意你的看法,但我在任何地方都找不到它的记录。
  • @Jeff Foster:我刚刚查看了用于String.splitPattern.split 的源代码,它使用在String 中实现的Charsequence.subSequence 作为对substring 的调用。 .
【解决方案2】:

如果您的 extractHeadWord 执行此操作 return new String(splitted[0]); 会发生什么。

它不会减少临时对象,但可能会减少应用程序的占用空间。我不知道 split 是否与子字符串大致相同,但我想确实如此。 substring 在原始数据上创建一个新视图,这意味着完整的字符数组将保存在内存中。显式调用new String(string) 将截断数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-27
    • 2013-10-06
    • 1970-01-01
    • 1970-01-01
    • 2017-10-03
    相关资源
    最近更新 更多