Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как читать XML (SAX) частями? быстрые переходы по файлу 
:(
    Опции темы
Sardar
Дата 7.2.2006, 13:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: 4
Всего: 317



Есть масса логов, пишуться java.util.logging через XMLFormatter. Получаю длиннющую (в реале и на пол гига, не шучу) простыню, которую нужно уметь быстро просматривать.

При старте нужно зачитать первую сотню записей, показать, дабы юзер не думал что прога тормозит. Отдельный тред пробегаеться по всему файлу, строит графическую полоску (удобно видеть где что в логе) и индексы. Как только индекс [номер записи : позиция в файле] доступно, можно спокойно скролить и прыгать в любое место.

Вопрос: как реализовать быстрые переходы по файлу, альтернатива reset/skip? Или есть у кого результаты тестов этих операций под разными платформами (интересует RHE Linux, Solaris)? Или просто совет кто уже делал подобное?

В итоге пишу Reader -> InputSource -> XMLReader.parse, так, что последний не должен заметить что прыгаем по файлу, как будто одна длинная простыня.

Название топу дал такое, т.к. вопрос больше как сабж. лучше сделать, может и не нужно вовсе свой Reader писать smile


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
LSD
Дата 7.2.2006, 15:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(Sardar @ 7.2.2006, 13:17 Найти цитируемый пост)
Вопрос: как реализовать быстрые переходы по файлу, альтернатива reset/skip? Или есть у кого результаты тестов этих операций под разными платформами (интересует RHE Linux, Solaris)? Или просто совет кто уже делал подобное?

Похожий вопрос был у Stampede, только там был не Reader а CharSequence. Доработка его кода понадобится, но хоть что-то.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Stampede
Дата 7.2.2006, 19:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гносеолог
**


Профиль
Группа: Участник Клуба
Сообщений: 963
Регистрация: 25.4.2005
Где: Calgary, Alberta, Canada

Репутация: 24
Всего: 144



Цитата(LSD @ 7.2.2006, 15:40 Найти цитируемый пост)

Похожий вопрос был у Stampede, только там был не Reader а CharSequence.


Я тоже сперва об этом подумал, но потом прикинул, что оно скорее всего не подойдет: если регекспу пофиг с какого места парсить, то XML ридеру таки нужен контекст.

Другое дело, что можно при первом проходе SAX парсером отлавливать начало и конец уаждой отдельной записи и заносить эту инфу в таблицу. А потом по мере скроллинга восстанавливать по номеру записи ее смещение, считывать из RandomAccessFile полный текст соответствующего ей XML элемента, и тогда уже добирать всю остальную инфу, относящуюся к записи, путем парсинга этого элемента.

У меня кстати примерно на таком принципе построен вьюер тех здоровых файлов, про которые я писал в упомянутом топике. Причем не просто вьюер, а вьюер с подсветкой найденных элементов. И работает, кстати, весьма шустро. Так что есть смысл попробовать.

PM WWW   Вверх
LSD
Дата 7.2.2006, 21:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Стандартный XML парсер так работать не сможет конечно, так как не любую структуру можно так распарсить. Но тут структура XML очень простая, и это можно использовать.
В принципе можно написать свой Reader который бы позволил парсить файл с произвольной позиции (есть пара идей).

Sardar подкинь структуру XML, по возможности в виде схемы.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Sardar
Дата 7.2.2006, 22:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: 4
Всего: 317



Цитата(LSD @ 7.2.2006, 20:41 Найти цитируемый пост)
подкинь структуру XML

Пишеться через java.util.logging.XMLFormatter, пример вывода и DTD

Цитата(Stampede @ 7.2.2006, 18:03 Найти цитируемый пост)
то XML ридеру таки нужен контекст

Для любого XML конечно нужен контекст, но логи это всё таки поток обьектов без навороченной структуры. Отсюда идея пока так:

[стрим из файла] -> {мой стрим/ридер с методом seek} -> [XMLReader] -> {логика} -> {анализатор}

//в фигурных моё, в квадратных классы из стандартной либы

Т.е. оборачиваю бычный стрим своим wrapper'ом, что (пока) методами reset/skip будет свободно перемещаться по стриму. Памяти кушать могут мало, потому хранить прочитанное долго не буду, стрим должен поддерживать reset(). Логика делает что нужно для задачи, одновременно посылает в анализатор уведомления [начался требуемый обьект, закончился требуемый обьект]. Таким образом должен создаваться индекс с позициями обьектов.

Если пользователь решит скролить назад, то позиции имеем, если вперёд, то нужно прочитать на перёд обновляя индекс. Идея не плохая, но что то не понял как узнать на каком символе сейчас находимся, SAX парсер не даёт контекстной информации... Интерфейс Locator есть, но всё натыкаюсь что "пользователь должен имплементировать сию функциональность". Может плохо искал...

Отсюда проблема: как узнать на каком символе сейчас находимся получая SAX события?

Если парсер ещё и буфферизует сам символы или события на перёд, то идее конец... придёться брать другой SAX парсер. Вроде апачи что то мощное имеют, все кто знаком с альтернативными парсерами откликнитесь smile


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
LSD
Дата 8.2.2006, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Цитата(Sardar @ 7.2.2006, 22:25 Найти цитируемый пост)
Памяти кушать могут мало, потому хранить прочитанное долго не буду, стрим должен поддерживать reset().

FileInputStream не поддерживает mark(), только BufferedInputStream который делает это все за счет кеша в памяти.

Я честно говоря не понял зачем тебе понадобилось знать на каком символе сейчас находимся получая SAX события, что это тебе даст? Все равно парсер нельзя остановить или сказать ему парсить обратно.

Я бы сделал так: пишем свой java.io.Reader, которому указываем смещение и количество байт которое надо прочитать. Наш Reader читает файл начиная с этого смещения и ищет открывающий тег (<record>) как только находит выдает:
Код
<?xml version="1.0"?>
<log>
<record>
...

и далее все что прочтет пока не превысит лимит прочитанных байт, тогда ждет закрывающий тег (</record>) и в дополнение к нему выдает закрывающий </log>. При этом мы можем использовать любой парсер хоть SAX хоть DOM.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Sardar
Дата 8.2.2006, 13:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: 4
Всего: 317



Цитата(LSD @ 8.2.2006, 11:30 Найти цитируемый пост)
Все равно парсер нельзя остановить или сказать ему парсить обратно

А мне и не нужно останавливать парсер, он вообще не знает о переходах, получает инфу как одну большую простыню.

Цитата(LSD @ 8.2.2006, 11:30 Найти цитируемый пост)
Я бы сделал так: пишем свой java.io.Reader

Ага, говорим об одном и том же, просто я задумался чуть дальше. Как сказать своему ридеру, что с текущей позиции начался новый обьект? Ридер должен тогда занести позицию в индекс [порядковый номер обьекта => смещение], далее прыгать можно сразу пользуя порядковый номер обьекта.

Проблемы:
  • если парсер читает на перёд, то ридер уебжит далеко вперёд, в это время получив очередной тег соображаем что здесь начало обьекта, пытаемся сказать об этом ридеру, а он уже чёрт знает где...
  • если получать позиции тегов в документе(offset) в символах, как все человеческие парсеры делают, то тоже можно двигаться, но возникнут следующие проблемы:
    • как заюзать Locator, в доке что то размытое, имплементации интерфейсу не нашёл...
    • требуеться прослойка что будет разбираться с UTF и подобными кодировками. Можно на манер Stampede, но позиции хранить регионом, т.е. для всего английского текста будет по сути одно вхождение. Эффективно, но вряд ли реализую что нибудь кроме UTF-8 и UTF-16, что плохо.
    • если парсер читает на перёд, то нужно как то очищать его буффер.

Млин, а начиналось как весьма простая задача... smile


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
LSD
Дата 11.2.2006, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 210
Всего: 538



Значита так:
С Locator я разобрался, там все просто как 3 копейки. Когда ты задаешь свой DefaultHandler устанавливает ему свой Locator (если конечно парсер поддерживает такую фишку). Парсер из JDK 1.5 поддерживает, юзать так:
Код
public class PrintStreamHandler extends DefaultHandler
{
  private PrintStream out;
  private PrintStream err;
  private Locator locator;

  public PrintStreamHandler(PrintStream out, PrintStream err)
  {
    this.out = out;
    this.err = err;
  }

  public void setDocumentLocator(Locator locator)
  {
    this.locator = locator;
  }

  private String getPosition()
  {
    if(locator == null)
      return "";
    return " at line: " + locator.getColumnNumber() + ", column: " + locator.getColumnNumber();
  }

  public void startDocument() throws SAXException
  {
    out.println("Document start" + getPosition());
  }

  public void endDocument() throws SAXException
  {
    out.print("Document end" + getPosition());
  }

  public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
  {
    out.println("  element " + qName + " start" + getPosition());
  }

  public void endElement(String uri, String localName, String qName) throws SAXException
  {
    out.println("  element " + qName + " end" + getPosition());
  }

  public void characters(char ch[], int start, int length) throws SAXException
  {
    String str = new String(ch, start, length).trim();
    out.println("    data: '" + str + "'" + getPosition());
  }

  public void warning(SAXParseException e) throws SAXException
  {
    err.println("WARNING" + getPosition() + ": " + e);
  }

  public void error(SAXParseException e) throws SAXException
  {
    err.println("ERROR: " + e);
  }

  public void fatalError(SAXParseException e) throws SAXException
  {
    err.println("FATAL: " + e);
  }
}

Правда это мало помогает, т.к. там идут координаты в строка/символ, а для Reader надо в байтах.

Парсер читает столько данных сколько есть в потоке. Если скармливать ему по одному символу, то начало/конец тега получим как только он получит последний символ.


Теперь к Reader-у считать данные из произвольной позиции файла и отдать их не проблема, вопрос только в этих позициях. Можно хранить два массива long в одном номер записи, в другом смещение в байтах от начала файла. Но тут вылезает вопрос памяти, если считать, что файл имеет размер 1Гб, а размер одной записи 300 байт, то у нас будет около 3 500 000 записей и на это дело надо будет 58Мб. Так что придется хранить каждую 16 или даже 32 запись. Но это в принципе не проблема, проблема в том как заполнить этот индекс.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0527 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.