2016-06-19 15 views
0

Я пытаюсь создать java-программу, которая разбивает выбранный файл XML.XML-расщепление BIG-файла с использованием Java

XML выборка данных файла:

<EmployeeDetails> 
<Employee> 
<FirstName>Ben</FirstName> 
</Employee> 
<Employee> 
<FirstName>George</FirstName> 
</Employee> 
<Employee> 
<FirstName>Cling</FirstName> 
</Employee> 
<EmployeeDetails> 

И так, у меня есть этот 250Mb XML файл муравей всегда боль в заднице, чтобы открыть его внешнюю программу и вручную разбить его, чтобы иметь возможность быть читаемыми с другие (не все ноутбук/настольный компьютер может открыть такой большой файл). Поэтому я решил создать программу Java, которая будет иметь эту функцию: -Выберите файл XML (уже сделано) -Split-файл на основе # тегов, например. (В текущем файле есть 100 тыс. Тегов. Я спрошу пользователя программы о том, как Сотрудник, которого он/она хочет для разбитого файла (например, 10k на файл) -Split файл (уже сделано)

Я просто хочу попросить о помощи, как я могу выполнить вторую задачу, уже в 3 -4 дня проверяя, как же я могу это сделать, или это даже возможно (на мой взгляд, конечно, есть).

Любой ответ будет оценен.

Приветствия, Grimm.

+0

Для Java у вас есть два варианта - DOM (объектная модель документа), где весь файл считывается в память. Это будет немного проще реализовать, но потребует разумного объема памяти - JVM 1 ГБ должен быть достаточным, если программа не делает ничего другого. Модель SAX (потоковая передача) может обрабатывать файл, даже если он стал 100 ГБ - он читает файл понемногу и имеет обратные вызовы, когда, например, он видит новый тег. [Этот пост] (http://stackoverflow.com/questions/6828703/what-is-the-difference-between-sax-and-dom) идет немного подробнее. – stdunbar

+0

У вас также есть третий вариант: выполните преобразование XSLT. –

+0

И четвертый выбор: StAX. – biziclop

ответ

0

Простое решение на заказ. Если XML всегда имеет эти разрывы строк, как показано, обработка XML не требуется.

Path originalPath = Paths.get("... .xml"); 
try (BufferedReader in = Files.newBufferedReader(originalPath, StandardCharsets.UTF_8)) { 
    String line = in.readLine(); // Skip header line(s) 

    line = in.readLine(); 
    for (int fileno; line != null && !line.contains("</EmployeeDetails>"); ++fileno) { 
     Path partPath = Paths.get("...-" + fileno + ".xml"); 
     try (PrintWriter out = new PrintWriter(Files.newBufferedWriter(partPath, 
       StandardCharsets.UTF_8))) { 
      int counter = 0; 
      out.println("<EmployeeDetails>"); // Write header. 
      do { 
       out.println(line); 
       if (line.contains("</Employee>") { 
        ++counter; 
       } 
       line = in.readLine(); 
      } while (line != null && !line.contains("</EmployeeDetails>") 
        && counter < 1000); 
      out.println("</EmployeeDetails>"); 
     } 
    } 
} 
+0

Это довольно хорошо и работает, но, по-видимому, как и моя проблема в приведенных выше комментариях, не все компьютеры могут открывать тяжелый XML-файл, ожидающий эту ошибку, как я уже говорил до «Исключение в потоке» main «java.lang.OutOfMemoryError: Java heap space " – Grimmjow

+0

Это странно, попробуйте использовать только BufferedWriter, поскольку PrintWriter, к сожалению, зачищает исключения под ковром. Вы что-то читаете рядом? –

+0

Другая идея: используйте gz-сжатие xml для 'xxx.xml.gz' и используйте' new InputStreamReader (новый GZipInputStream (... '. –

1

Предполагая плоскую структуру, в которой корневой элемент документа R имеет большое количество детей с именем X, следующее преобразование XSLT 2.0 будет разбивать файл на каждый элемент Nth X.

<t:transform xmlns:t="http://www.w3.org/1999/XSL/Transform" 
    version="2.0"> 
    <t:param name="N" select="100"/> 
    <t:template match="/*"> 
    <t:for-each-group select="X" 
         group-adjacent="(position()-1) idiv $N"> 
     <t:result-document href="{position()}.xml"> 
     <R> 
      <t:copy-of select="current-group()"/> 
     </R> 
     </t:result-document> 
    </t:for-each-group> 
    </t:template> 
</t:transform> 

Если вы хотите запустить это в потоковом режиме (без создания исходного дерева в памяти), то (а) добавить <xsl:mode streamable="yes"/>, и (б) запустить его с помощью XSLT 3.0 процессора (Saxon-EE или Exselt).

+0

Это работает как ожидалось. Теперь у меня есть 2 варианта вашего комментария и ниже. Но, по-видимому, проверка 2 ответа невозможна. – Grimmjow