Java 读取重文本文件

Java 读取重文本文件,java,android,io,Java,Android,Io,我必须读取一个大的文本文件(大约5兆字节) 对于读取此文件,我使用了BufferedReader(),但这会导致内存泄漏和堆增长,是否有其他选项来优化我的代码 StringBuffer sb = new StringBuffer(); BufferedReader reader = new BufferedReader(new FileReader(vCache)); String line = null;

我必须读取一个大的文本文件(大约5兆字节)

对于读取此文件,我使用了
BufferedReader()
,但这会导致内存泄漏和堆增长,是否有其他选项来优化我的代码

            StringBuffer sb = new StringBuffer();
            BufferedReader reader = new BufferedReader(new FileReader(vCache));
            String line = null;

            while ((line = reader.readLine()) != null) 
            {
                sb.append(line);
            }
您正在解析JSON

如果输入文件存在,可以通过删除修饰(例如缩进、换行等)使输入文件变小

您还可以尝试直接从流读取的解析器,希望它不需要一次缓冲所有内容。例如,Android提供了,它允许您自己解析流并控制数据结构,这意味着您可以使用内存效率更高的结构,而且它也不会缓冲整个流。不幸的是,它是在API级别11中添加的,因此向后兼容性可能是一个问题


另一种选择是,如果顶级对象是数组,则将其拆分为几个较小的数组,可能位于不同的文件中,分别解析它们并合并子数组。如果基本对象具有类似的结构,则可以在合并之前将其转换为Java对象,这样会有更紧凑的内存结构。

尝试使用
InputStream
而不是
BufferedReader

try {
    InputStream is = new FileInputStream(vCache);
    byte[] b = new byte[is.available()];
    is.read(b);
    String text = new String(b);
}

我猜你在读本地文件。在这种情况下,最好将整个文件读入字节数组,然后转换为字符串:

InputStream is = new FileInputStream(vCache);
byte[] buffer = new byte[is.available()];
is.read(buffer);
is.close();
jsonContent = new String(buffer, "UTF-8");

然而,将Android中如此大的文件读入内存,可能仍然会带来问题。我想说,如果你需要读取一个5 MB的json文件,你可能没有正确构造你的应用程序。

默认的
BufferedReader使用的
bufferSize
8KB
,但是因为你是逐行读取,所以累积会更多。要改善这一点,您可以使用:


BufferedReader(读取器输入,int sz)
您的代码。。。如文所述。。。读取行并将其累加到
StringBuilder
中。仅仅是您正在累积行的事实就是一种内存泄漏

防止泄漏的最佳方法是将应用程序更改为如下方式:

    BufferedReader reader = new BufferedReader(new FileReader(vCache));
    String line = null;
    while ((line = reader.readLine()) != null) {
        process(line);
    }
    StringBuilder sb = new StringBuilder(fileSizeInCharacters);
换句话说,不要在内存中累积这些行。在阅读时对其进行处理,然后将其丢弃


如果您的处理需要在内存中累积行,那么如果您像这样分配
StringBuilder
,您将获得更好的内存使用率:

    BufferedReader reader = new BufferedReader(new FileReader(vCache));
    String line = null;
    while ((line = reader.readLine()) != null) {
        process(line);
    }
    StringBuilder sb = new StringBuilder(fileSizeInCharacters);
这将避免重新分配的需要,在最坏的情况下,重新分配需要的字符数是文件大小(以字符为单位)的3倍

然而,你迟早会遇到同样的问题。在内存中累积文件内容不会缩放


您的评论表明这确实是一个JSON处理问题。以下是关于流式JSON处理主题的问答:


流式API的思想是,您不需要将JSON“对象”转换为表示整个内容的内存树结构。

发送JSON,使每一行对应一个完整的db行和格式良好的JSON。这样,您就不必同时处理整个文件

//StringBuffer sb = new StringBuffer();
BufferedReader reader = new BufferedReader(new FileReader(vCache));
String line = null;

while ((line = reader.readLine()) != null)  {
  //Parse JSON
  //Insert into local SQLite DB.
}

您的日志很昂贵(字符串conact),而且可能内存泄漏……为什么要读取5MB的文件?请解释这背后的要求?@krishnakumarp我需要获取我的所有web服务器数据库行,将其保存在文本文件中,以json格式解析,最后将其逐个插入我的本地数据库。在您的web服务器中进行解析,然后从Android加载json,尝试构造文件,使每个db行位于一行文件中,并逐行处理,而不将其保留在内存中(StringBuffer)。看到我的回答谢谢Vlad,是的,我正在尝试解析json,你能给我一个从流中读取json的例子吗?尝试使用Jackson json解析器,你可以直接从
inputStream