【问题标题】:Fast & Efficient Way To Read Large JSON Files Line By Line in Java在 Java 中逐行读取大型 JSON 文件的快速高效方法
【发布时间】:2017-04-10 16:24:56
【问题描述】:

我在JSON 文件中有 1 亿条记录,需要一种高效且最快的方法来从java 中的JSON 文件中读取数组数组。

JSON 文件看起来像:

[["XYZ",...,"ABC"],["XYZ",...,"ABC"],["XYZ",...,"ABC"],...,["XYZ",...,"ABC"],
 ["XYZ",...,"ABC"],["XYZ",...,"ABC"],["XYZ",...,"ABC"],...,["XYZ",...,"ABC"],
 ...
 ...
 ...
 ,["XYZ",...,"ABC"],["XYZ",...,"ABC"],["XYZ",...,"ABC"]]

我想逐行读取这个JSON文件:

先阅读:

["XYZ",...,"ABC"]

然后:

["XYZ",...,"ABC"]

等等:'

...
...
...
["XYZ",...,"ABC"]

我如何读取这样的JSON 文件,我知道它看起来并不完全像JSON 文件,但我需要以这种格式读取此文件并保存为.JSON

【问题讨论】:

  • 你的意思是JSON??还是我错过了什么?
  • 输入错误对不起 JSON。
  • 首先,该文件应位于快速 SSD 上。接下来,您可以尝试使用BufferedReader 阅读它,看看这是否已经为您提供了 SSD 能够提供的最大速度。如果没有尝试FileChannel.map,看看你能从生成的 ByteBuffer 中读取多快。顺便提一句。如果您想多次读取文件,请确保您的计算机中有足够的空闲 RAM 以允许操作系统在内存中缓冲整个文件。

标签: java performance file-io java.util.scanner bufferedreader


【解决方案1】:

您可以使用JSON Processing API (JSR 353),以流式方式处理您的数据:

import javax.json.Json;
import javax.json.stream.JsonParser;

...

String dataPath = "data.json";

try(JsonParser parser = Json.createParser(new FileReader(dataPath))) {
     List<String> row = new ArrayList<>();

     while(parser.hasNext()) {
         JsonParser.Event event = parser.next();
         switch(event) {
             case START_ARRAY:
                 continue;
             case VALUE_STRING:
                 row.add(parser.getString());
                 break;
             case END_ARRAY:
                 if(!row.isEmpty()) {
                     //Do something with the current row of data 
                     System.out.println(row);

                     //Reset it (prepare for the new row) 
                     row.clear();
                 }
                 break;
             default:
                 throw new IllegalStateException("Unexpected JSON event: " + event);
         }
     }
}

【讨论】:

  • 我声明了一个 HashMap 并将行值放在 HashMap 中,但是如果我想在 HashMap 中获取一个值,它会返回一个空列表 []。这是由于 row.clear() 语句而发生的。如何解决这个问题?
  • @AAKM 然后重新创建行,而不是清除它:row=new ArrayList&lt;&gt;()(在 END_ARRAY 块中)。而且你最好确保你有足够的内存在一个巨大的 HashMap 中存储 1 亿条记录。
  • 替换 row.clear() 行,然后执行它需要很长时间。我使用 hashmap 来更有效地搜索数据,因此还有其他方法可以存储大量数据并通过使用最少的内存来高效搜索。
  • @AAKM - 这完全取决于你想对你的数据做什么,HashMap 没问题,只要你有足够的内存。
【解决方案2】:

您可以使用JsonSurfer 通过 JsonPath 提取所有内部 JSON 数组:$[*]

    JsonSurfer surfer = JsonSurferJackson.INSTANCE;
    surfer.configBuilder().bind("$[*]", new JsonPathListener() {
        @Override
        public void onValue(Object value, ParsingContext context) {
            System.out.println(value);
        }
    }).buildAndSurf(json);

它不会将整个 Json 加载到内存中。 JSON数组会被一一处理。

【讨论】:

  • 这个 Surfer 可以支持 Java8 吗?我收到错误ANTLR Tool version 4.7.1 used for code generation does not match the current runtime version 4.8ANTLR Runtime version 4.7.2 used for parser compilation does not match the current runtime version 4.8ANTLR Tool version 4.7.1 used for code generation does not match the current runtime version 4.8ANTLR Runtime version 4.7.2 used for parser compilation does not match the current runtime version 4.82021-06-23 21:42:46.673 INFO 23946 --- [ main] ConditionEvaluationReportLoggingListener :
猜你喜欢
  • 2012-10-20
  • 2011-08-13
  • 2013-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-23
相关资源
最近更新 更多