【问题标题】:Convert XML to JSON efficiently for Huge Files为大文件有效地将 XML 转换为 JSON
【发布时间】:2019-01-28 06:43:12
【问题描述】:

我有几个要转换为 JSON 的 XML 文件(大小为 GB)。我可以使用 JSON 库(org.json - https://mvnrepository.com/artifact/org.json/json/20180813)轻松转换小型文件(以 KiloBytes 为单位)。

这是我正在使用的代码

            static String line="",str="";
            BufferedReader br = new BufferedReader(new FileReader(link));
            FileWriter fw = new FileWriter(outputlink);
            JSONObject jsondata = null;

            while ((line = br.readLine()) != null) 
            {   
                str+=line;  
            }
            jsondata = XML.toJSONObject(str);

但是大文件(即使是

更新

我已经更新了代码,我正在逐段将 XML 写入 JSON

我的 XML:

<PubmedArticleSet>
     <PubmedArticle>
     </PubmedArticle>
     <PubmedArticle>
     </PubmedArticle>
...
</PubmedArticleSet>

所以我忽略了根节点&lt;PubmedArticleSet&gt;(我稍后会添加)将每个&lt;PubmedArticle&gt; &lt;/PubmedArticle&gt;转换为JSON并一次写入

         br = new BufferedReader(new FileReader(link));
         fw = new FileWriter(outputlink,true);
         StringBuilder str = new StringBuilder();
         br.readLine(); // to skip the first three lines and the root 
         br.readLine();
         br.readLine();

         while ((line = br.readLine()) != null) {


            JSONObject jsondata = null;

            str.append(line);
            System.out.println(str);
            if (line.trim().equals("</PubmedArticle>")) { // split here


                jsondata = XML.toJSONObject(str.toString());

                String jsonPrettyPrintString = jsondata.toString(PRETTY_PRINT_INDENT_FACTOR);
                fw.append(jsonPrettyPrintString.toString());

                System.out.println("One done"); // One section done
                str= new StringBuilder();


            }
           }
            fw.close();

我不再收到 HeapError,但处理 ~300 MB 范围文件仍需要数小时。请提供任何建议以加快此过程。

【问题讨论】:

  • 这就是用纯 C 编写的 Json 编码器/解码器应该派上用场的地方。 Parsing XML in Pure C & Parsing JSON using C。您可以尝试使用 JNI 将它们移植到 Java 中。
  • 有几个 Java 库可以为您处理这种转换(并且以更有效的方式)。有关示例,请参阅此答案:stackoverflow.com/a/39493394/1420773
  • XML 数据的结构是否可以将其分成块并单独序列化?如果是这样,您可以在阅读后将每个块写出来,而不是全部加载。
  • 当您说“JSON 库”时,您需要说出是哪一个。有几十个。
  • @MichaelKay “JSON 库”是指 JSON 库。 ( org.json )我已经更新了这个问题。如果有的话,请建议任何更好的替代库来完成任务。

标签: java xml


【解决方案1】:

这句话是扼杀你表现的主要原因:

str+=line;

这会导致大量 String 对象的分配、复制和释放。

你需要使用StringBuilder:

StringBuilder builder = new StringBuilder();
while ( ... ) {
    builder.append(line);
}

它也可能有助于(在较小程度上)以更大的块而不是逐行读取文件。

【讨论】:

  • 仍然不够,在 380 MB 文件上测试在 builder.append(line) 处出现 OutofMemory 错误;
  • 问题是要慢,而不是内存不足。您是否允许 JVM 使用更多内存(-Xmx 选项)?
  • 是的,当前设置在 ini -Xms512m -Xmx1536m
  • 一个 300MB 的文件将需要 600 MB 来存储字符数据,您还将整个对象保存在内存中(大概是两次,JSON 和 XML)所以 1.5G 可能不够。
  • 当然,但这不是您最初的问题。第二个问题的解决方案是流式传输(即逐部分处理文件并在您进行时输出部分结果)。这取决于 XML 和 JSON 的结构有多难(甚至有多可行)。最好再问一个问题,给出各自结构的详细信息。
【解决方案2】:

读取大文件的IO操作非常耗时。尝试利用库为您处理此问题。例如apache commons IO:

File xmlFile= new File("D:\\path\\file.xml");
String xmlStr= FileUtils.readFileToString(xmlFile, "UTF-8");
JSONObject xmlJson = XML.toJSONObject(xmlStr);

【讨论】:

  • 我想知道,StringBuilderWriterStringBuilder 好吗?我看到 Apache Commons IO FileUtils 使用了它behind the scene..
  • 来自 javadoc,来自您的链接:输出到 StringBuilder 的 Writer 实现。这个实现,作为 java.io.StringWriter 的替代方案,提供了一个非同步(即用于单线程)实现以获得更好的性能。为了安全使用多个线程,应该使用 java.io.StringWriter。
猜你喜欢
  • 2023-03-09
  • 2017-12-14
  • 1970-01-01
  • 2012-06-17
  • 2013-01-28
  • 2017-06-18
  • 2016-07-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多