Каков самый быстрый способ преобразовать файл XML в файл JSON в Java?

В настоящее время у меня есть куча файлов XML (каждый размером 16 КБ), которые необходимо преобразовать в JSON, а затем записать в новые файлы. У меня есть рабочая реализация, но она очень медленная.

Что я делаю, так это захватываю каждый файл в каталоге, преобразовываю данные XML в строку, создаю объект JSON этой строки с помощью org.json, а затем использую FileWriter для записи его в файл.

import org.json.JSONObject;
import org.json.XML;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import org.apache.commons.io.FilenameUtils;

public class TestConvert {

    public static void main(String[] args) {

        final File xmlFolder = new File("C:\\files\\xml_files");
        final File jsonFolder = new File("C:\\files\\json_files");

        for(File fileEntry: xmlFolder.listFiles()){
            try {
                String xml = new String(Files.readAllBytes(fileEntry.toPath()), StandardCharsets.UTF_8);
                JSONObject obj = XML.toJSONObject(xml);

                String completeDir = jsonFolder + "\\" + FilenameUtils.removeExtension(fileEntry.getName()) + ".json";

                FileWriter file = new FileWriter(completeDir);
                obj.write(file);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Это работает, однако в настоящее время я тестирую это с файлами XML ~ 370 000, и время работы составляет чуть более 45 минут. Это кажется чрезмерным, и я действительно хотел бы сократить время, необходимое для завершения этого.


person djharten    schedule 13.06.2019    source источник
comment
Вы можете использовать многопоточность, чтобы завершить процесс за еще меньшее время. Создайте количество потоков и дайте каждому потоку несколько файлов xml.   -  person Vishal Patel    schedule 13.06.2019
comment
Насколько велики ваши файлы XML? Сколько элементов и глубины? Это может быть удивительно быстрое время для всего, что мы знаем!   -  person Jamie    schedule 13.06.2019
comment
Это хорошая мысль, Джейми. Спасибо. Размер каждого файла составляет 16 КБ. Я считаю, что он идет на глубину 10 или 11.   -  person djharten    schedule 13.06.2019
comment
Вы рассматривали xslt?   -  person daniu    schedule 13.06.2019
comment
не знаю, будет ли это быстрее или нет, но попробуйте библиотеку jackson, используйте пул потоков и разделите разные файлы на разные потоки.   -  person sero    schedule 13.06.2019
comment
Есть ли особый способ, которым я могу заставить потоки захватывать разные XML-файлы и писать новые, не сообщая им об этом явно? Скажем, если бы я не знал ни одного из имен файлов или их количества, можно ли было бы это сделать? Или мне нужно настроить этот процесс вручную?   -  person djharten    schedule 13.06.2019


Ответы (3)


Вы можете использовать это: https://github.com/stleary/JSON-java

<dependency>
  <groupId>org.json</groupId>
  <artifactId>json</artifactId>
  <version>20180813</version>
</dependency>

И файл Java:

import org.json.JSONObject;
import org.json.XML;

public class Main {

    public static int PRETTY_PRINT_INDENT_FACTOR = 4;
    public static String TEST_XML_STRING =
        "<?xml version=\"1.0\" ?><test attrib=\"moretest\">Turn this to JSON</test>";

    public static void main(String[] args) {
        try {
            JSONObject xmlJSONObj = XML.toJSONObject(TEST_XML_STRING);
            String jsonPrettyPrintString = xmlJSONObj.toString(PRETTY_PRINT_INDENT_FACTOR);
            System.out.println(jsonPrettyPrintString);
        } catch (JSONException je) {
            System.out.println(je.toString());
        }
    }
}
person Said    schedule 14.06.2019

Вы могли бы попробовать использовать BufferedOutputStream или следующее. Я использовал Files.list, так как традиционный File.listFiles работает медленно для больших каталогов.

    final Path xmlFolder = Paths.get("C:\\files\\xml_files");
    final Path jsonFolder = xmlFolder.resolveSibling("json_files");

    Files.list(xmlFolder)
        .forEach(path -> {
        try {
            String xml = new String(Files.readAllBytes(fileEntry.toPath()),
                StandardCharsets.UTF_8);

            // 1
            final int initialXmlSize = 320 * 1024;
            JSONObject obj = XML.toJSONObject(xml);
            StringWriter xmlOut = new StringWriter(initialXmlSize);
            obj.write(xmlOut);
            String xml = xmlOut.toString();
            // 2

            String jsonFileName = path.getFileName().toString().replaceFirst("\\.[^\\.]+$",
                "") + ".json";
            Path xmlPath = jsonFolder.resolve(jsonFileName);
            Files.write(xmlPath, xml.getBytes(StandardCharsets.UTF_8));
        } catch (IOException e) {
            System.err.println("File " + path);
            e.printStackTrace();
        }
    }

Код между // 1 и // 2 можно было бы дополнительно оптимизировать, чтобы использовать только строки, без объектов DOM (XM, JSON). Одним из решений будет XSLT (хотя и быстрее?).

person Joop Eggen    schedule 14.06.2019

Библиотека Underscore-java имеет статический метод U.xmlToJson(xml). Я куратор проекта.

person Valentyn Kolesnikov    schedule 09.02.2020