如何在Android应用程序上阅读大型Base64文件(150MB)?

时间:2016-03-06 13:05:21

标签: java android

我试图在Android应用程序上阅读大小为base64的大(~ 150MB)文本文件。

该文件包含我需要解码的JSON字符串并将其转换为JSON对象,并在应用程序中使用它。问题是我在尝试读取此数据时遇到异常Out of Memory

该应用需要离线工作,因此我需要下载完整数据。

以下是代码:

    String localPath = getApplicationContext().getFilesDir().getPath().toString() ;
    String key = "dataFile.txt" ;

    StringBuilder text = new StringBuilder();
    File file=new File(localPath+"/"+ key);

    byte fileContent[] = new byte[3000];

    try ( FileInputStream fin = new FileInputStream(file)) {
        while(fin.read(fileContent) >= 0) {
            byte[] data = Base64.decode(fileContent, Base64.DEFAULT);
            try {
                text.append(new String(data, "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        obj = new JSONObject(text.toString());
    }catch (Exception e){
        e.printStackTrace();
    }

我怎样才能读到这种文件?

2 个答案:

答案 0 :(得分:2)

您正在尝试通过读取文件将整个文件读入text对象,迭代它并将每行附加到text。您可以从JSONObject对象中创建text,该对象仅在最后一步中对您的应用程序有用。

在这里,当您的代码到达行obj = new JSONObject(text.toString());时,您已经填充了几乎与输入文件大小相当的堆,因为这个完整的文件以{{1}的形式存在于内存中对象。然后,您可以制作此test个对象的JSONObject

您可以采取以下措施来解决此问题:

  1. 使用text以块的形式读取文件(可选)。使用BufferedReader可能有点慢,有一个缓冲区很好。
  2. 迭代文件并将条目放入read()text批次的1000对象中。
  3. 10000中准备JSONObject并将其附加到text
  4. 在处理下一批次之前清除obj对象,然后重复整个过程。
  5. 通过执行此操作,您只读取内存中的一小部分文件,并且text对象充当缓冲区,仅消耗少量内存。

    以下是示例代码段:

    text

答案 1 :(得分:2)

您唯一的选择是使用JSON streaming并对您感兴趣的事件做出反应。

import org.codehaus.jackson.*;

.....

JsonParser parser = new JsonFactory().createJsonParser( yourFileInputStream );
parser.configure( Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true );
parser.configure( Feature.ALLOW_SINGLE_QUOTES, true );
// add more features

for( JsonToken token = parser.nextToken(); null != token; token = parser.nextToken() ){
  switch( token ){
    case FIELD_NAME:
      doStuffWithName();
      break;

    case START_OBJECT:
      doObjectStart();
      break;

    case END_OBJECT:
      processObject();
      break;

    // other events
  }
}

我在4.0设备上使用了上述代码,并使用了10 MB的JSON文件。

PS。您需要先解码原始Base64文件。不确定您是否可以在java.io.Stream内动态执行此操作。在最坏的情况下,将Base64文件解压缩到plain-json中,然后使用上面的JSON流代码