Разбор больших XML-документов в JAVA
У меня есть следующая проблема:
У меня есть XML файл (около 1 ГБ), и вам нужно итерации вверх и вниз (т.е. не последовательно, один за другим), чтобы получить требуемые данные и выполнить некоторые операции над ним. Первоначально я использовал пакет DOM Java, но, очевидно, при анализе XML файла JVM достигает своего максимального пространства кучи и останавливается.
Чтобы решить эту проблему, одним из решений, которые я придумал, было найти другой парсер, который выполняет итерацию каждого элемента в XML, а затем я храню его содержимое во временной базе данных SQLite на моем жестком диске. Следовательно, таким образом, куча JVM не будет превышена, и как только все данные будут заполнены, я проигнорирую файл XML и продолжу свои действия во временной базе данных SQLite.
Есть ли другой способ, как я могу решить мою проблему?
Ответы
Ответ 1
SAX (простой API для XML) поможет вам здесь.
В отличие от анализатора DOM, синтаксический анализатор SAX не создает встроенную память представление XML-документа и, следовательно, быстрее и использует меньше Память. Вместо этого анализатор SAX информирует клиентов XML-документа структуры путем вызова обратных вызовов, то есть путем вызова методов на org.xml.sax.helpers.DefaultHandler
экземпляр, предоставленный парсеру.
Вот пример реализации:
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
DefaultHandler handler = new MyHandler();
parser.parse("file.xml", handler);
Где в MyHandler
вы определяете действия, которые необходимо предпринять, когда генерируются такие события, как начало/конец документа/элемента.
class MyHandler extends DefaultHandler {
@Override
public void startDocument() throws SAXException {
}
@Override
public void endDocument() throws SAXException {
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
}
// To take specific actions for each chunk of character data (such as
// adding the data to a node or buffer, or printing it to a file).
@Override
public void characters(char ch[], int start, int length)
throws SAXException {
}
}
Ответ 2
Если вы не хотите привязываться к ограничениям памяти, я настоятельно рекомендую вам использовать ваш текущий подход и хранить все в базе данных.
Разбор XML файла должен выполняться с помощью SAX parser
, как рекомендовал каждый (включая меня). Таким образом, вы можете создавать один объект за раз, и вы можете сразу же его перенести в базу данных.
Для последующей обработки (разрешения перекрестных ссылок) вы можете использовать SELECT
из базы данных, делать первичные ключи, индексы и т.д. Вы также можете использовать ORM (Eclipselink, Hibernate), если вам комфортно с этим.
На самом деле я не рекомендую SQLite, проще настроить сервер MySQL и хранить там данные. Позже вы можете даже повторно использовать данные XML (если вы не удалите).
Ответ 3
Если вы хотите использовать более высокий уровень, чем SAX, что может быть очень сложно для программирования, вы можете посмотреть потоковые преобразования XSLT, используя недавнюю версию Saxon-EE. Однако вы слишком расплывчаты в отношении точной обработки, которую вы делаете, чтобы узнать, будет ли это работать для вашего конкретного случая.
Ответ 4
если вам нужен дружественный к ресурсам подход для обработки очень большого xml, попробуйте это:
http://www.xml2java.net/xml-to-java-data-binding-for-big-data/
он позволяет обрабатывать данные по SAX-способу, но с преимуществом получать события высокого уровня (данные xml, отображаемые на java), и иметь возможность напрямую работать с этими объектами в вашем коде. поэтому он сочетает в себе удобство jaxb и удобство использования SAX.