Как добавить дочерний элемент в большой XML-файл, используя Java? - PullRequest
2 голосов
/ 18 февраля 2012

Я пытаюсь создать файл XML с использованием Java, который представляет собой набор координат GPS (GPX).Каждый раз, когда я получаю координаты от моего устройства Android (примерно 1 раз в секунду), мне нужно добавить результаты в существующий файл XML.Результат, который я ищу, показан ниже с элементом trkpt в качестве повторяющегося элемента.Проблема в том, что я не могу просто добавить новый trkpt в конец файла, потому что он должен находиться внутри родительского элемента trkseg.

До сих пор я пробовал два разных API, SIMPLEXML и JDOM.С SIMPLEXML я не мог понять, как добавить дочерний элемент в существующий файл, поэтому я переключился на JDOM.JDOM позволил мне добавить элемент trkpt, как показано ниже, но когда файл начал расти, он быстро замедлил пользовательский интерфейс программы.С JDOM я использовал SAXBuilder, чтобы снова открыть файл и добавить.Я думаю, проблема в том, что он должен был воспроизвести весь файл в памяти, прежде чем он добавил новый элемент и переписал файл.Таким образом, чем больше размер файла, тем более требовательной была операция на устройстве.Мне нужно решение, которое не проверяет / не копирует весь файл перед записью новых данных.Есть ли более эффективный способ сделать это с помощью Java или API для Java?Спасибо за любую помощь!

<?xml version="1.0" encoding="UTF-8"?>
<gpx xmlns="http://www.topografix.com/GPX/1/1">
        <trk>
            <trkseg>
                <trkpt lon="9.860624216140083" lat="54.9328621088893">
                    <ele>228.0</ele>
                </trkpt>
                <trkpt lon="9.860624216140100" lat="54.9328621088754">
                    <ele>234.0</ele>
                </trkpt>
                <trkpt lon="9.860624216140343" lat="54.9328621088678">
                    <ele>227.0</ele>
                </trkpt>
            </trkseg>
        </trk>
</gpx>

Ответы [ 4 ]

0 голосов
/ 19 февраля 2012

Предлагаю разбить файл xml на 3 части.

head.xml

<?xml version="1.0" encoding="UTF-8"?>
<gpx xmlns="http://www.topografix.com/GPX/1/1">
    <trk>
        <trkseg>

body.xml

<trkpt lon="9.860624216140083" lat="54.9328621088893">
    <ele>228.0</ele>
</trkpt>
<trkpt lon="9.860624216140100" lat="54.9328621088754">
    <ele>234.0</ele>
</trkpt>
<trkpt lon="9.860624216140343" lat="54.9328621088678">
    <ele>227.0</ele>
</trkpt>

tail.xml

        </trkseg>
    </trk>
</gpx>

теперь, когда вы получаете новые данные, просто добавьте их в body.xml

, чтобы прочитать XML-файл, используя SequenceInputStream, как показано ниже:

List<InputStream> list = new ArrayList<InputStream>(3);
list.add(new FileInputStream("head.xml"));
list.add(new FileInputStream("body.xml"));
list.add(new FileInputStream("tail.xml"));
InputStream xmlStream = new SequentialInputStream(Collections.enumeration(list));
0 голосов
/ 18 февраля 2012

Это звучит как идеальное приложение для SAX (найдите его в упаковке org.xml.sax); это потоковый API для доступа к XML и манипулирования им. SAX генерирует события для каждого элемента, с которым он сталкивается, что позволяет вам копировать файл в новый файл без необходимости разбирать его в большом дереве в памяти. Когда вы достигли конца вашего входного файла, просто добавьте новый элемент соответствующим образом перед обработкой конечного тега <trkseg>.

Конечно, ваш подход переписывать этот файл каждую секунду звучит сомнительно само по себе. Можете ли вы объединить информацию в более крупные сегменты? Вы можете записать информацию в отдельные файлы и собирать их в один файл через определенные интервалы (каждые 10/30/60 секунд).

0 голосов
/ 18 февраля 2012

Если это так просто, как указано здесь, вы можете просто использовать RandomAccessFile и искать длину файла минус несколько байтов (прямо перед корневым закрывающим тегом) и просто начать перезапись там.

0 голосов
/ 18 февраля 2012

Всегда существуют узкие места, когда дело доходит до ввода / вывода, особенно при повторном открытии / закрытии / повторном открытии файлов.

Обработчик DOM будет создавать целую древовидную структуру каждый раз, когда он открываетфайл, но очень эффективен, когда дело доходит до изменения этого дерева.

Итак, прежде всего, вам действительно нужно открывать, изменять, сохранять файл на каждом тике?Если нет, сохраните DOM файла в памяти и измените ссылку на XML.Сохранение, когда пользователь выходит из приложения или покидает представление.

Если вам нужно сохранять файл при каждом тике, вы все равно можете хранить DOM в памяти и сохранять его на диск только при каждом тике.

Если вам нужно открывать / сохранять / повторно открывать файл на каждом тике, не используйте никакую XML-библиотеку - просто используйте стандартный FileWriter или тому подобное, с ручным изменением содержимого - но он все равно будетбудет трудно поддерживать производительность, если файл становится действительно большим.

...