Android - OutOfMemory读取文本文件时

时间:2011-06-20 08:50:01

标签: java android dictionary io

我在android上制作一个字典应用程序。在启动期间,应用程序将加载.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];
}

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

是否有任何解决方案作为第二个代码段快速运行并且易于使用?

方面。

2 个答案:

答案 0 :(得分:4)

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

由于你没有在字符串的其余部分中处理它,你需要丢弃它以便它被垃圾收集,否则整个字符串将在内存中(但你只使用它的一部分)。

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

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

答案 1 :(得分:3)

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

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