Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблемы при парсинге оч. больших текстовых файлов, Проблемы при парсинге оч. больших тексто 
:(
    Опции темы
RayR
Дата 23.5.2007, 10:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 23.5.2007

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



Ситуация такая: есть текстовый файл размером ~ 150 MB (логфайл с прокси сервера).  Его нужно разбить на элементы, и эти элементы занести в БД (MSSQL8.1). Эта задача у меня без проблем была реализована на PHP5. Я брал данные из файла, разбивал их по определенному признаку командой "Explode" и заносил в БД(MSSQL8.1). На обработку такого файла уходило примерно 15-20 минут. 
Появилась необходимость сделать это на С++, для локального использования.
В С++Bulder6.0 я такой комманды не нашел и пришлось пользоваться этим: stringReplace (беру весь текст, по ключевому признаку делаю замену текста на символ перехода строки и заношу это в массив. В результате получается массив с примерно миллионом строк.). Все вроде нормально работает, но только если размер файла не превышает 25-30 метров. Если больше, то время выполнения задачи растет со страшной скоростью. Файл в 50 метров не смог развернуться за четыре часа, и это при том, что процессор был загружен на 100%. Причем до операции передачи данных в БД не доходит дела вообще, т.е. он затыкается на этапе разбения файла на куски. 

Оперативки на компе 2 гига, проц - Pentium4 3000 MHz. 
При выполнении задачи использование опреативки и файла подкачки подскакивает до ~50 %, проц - 100%.

Что посоветуете, знатоки, как решить эту проблему?
Заранее благодарен.
PM MAIL   Вверх
SenkraD
Дата 23.5.2007, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 3.2.2006
Где: Украина::Киев

Репутация: 3
Всего: 23



RayR,  признак деления на строки это символ или подстрока?
Если первое то посмотри TStringList и его свойства СommaText, DelimitedText, Delimiter, QuoteChar
А если второе, то можно создать невидимый TMemo или TRichEdit и воспользоватся TReplaceDialog.

Возникнут непонятки с реализацией - спрашивай. Да, ещё как быстро они работают я не знаю.
И ещё один вопрос - строки одинаковой длины (понимаю наивно, но всё же)

P.S. сильно не критиковать - пишу на скорую руку с головы


--------------------
 Имеющий язык - да не убоится спросить! 
user posted image
PM MAIL ICQ   Вверх
HappyLife
Дата 23.5.2007, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 642
Регистрация: 17.5.2006

Репутация: нет
Всего: 8



А как насчет оптимизации?. 
Не читай весь файл. Читай его кусками и обрабатывай.
После того как прочел нужную часть для одной строки БД, заноси. Затирай её и читай следующий кусочек.

PM MAIL   Вверх
RayR
Дата 23.5.2007, 11:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 23.5.2007

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



Цитата(SenkraD @ 23.5.2007,  10:57)
RayR,  признак деления на строки это символ или подстрока?
Если первое то посмотри TStringList и его свойства СommaText, DelimitedText, Delimiter, QuoteChar
А если второе, то можно создать невидимый TMemo или TRichEdit и воспользоватся TReplaceDialog.

Возникнут непонятки с реализацией - спрашивай. Да, ещё как быстро они работают я не знаю.
И ещё один вопрос - строки одинаковой длины (понимаю наивно, но всё же)

P.S. сильно не критиковать - пишу на скорую руку с головы

Признак деления - это строка(ip-адрес, первые две триады): "192.168."
PM MAIL   Вверх
SenkraD
Дата 23.5.2007, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 3.2.2006
Где: Украина::Киев

Репутация: 3
Всего: 23



ну тогда наверно, через реплейс диалог.
Попроси модераторов перенести тему в C++Builder - бистрее поможем


--------------------
 Имеющий язык - да не убоится спросить! 
user posted image
PM MAIL ICQ   Вверх
RayR
Дата 23.5.2007, 11:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 23.5.2007

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



Цитата(HappyLife @ 23.5.2007,  11:01)
А как насчет оптимизации?. 
Не читай весь файл. Читай его кусками и обрабатывай.
После того как прочел нужную часть для одной строки БД, заноси. Затирай её и читай следующий кусочек.

С этого момента, пожалуйста, поподробней! Если не трудно, то простой пример, или список функций, с помощью которых это можно сделать.
PM MAIL   Вверх
dumb
Дата 23.5.2007, 12:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: нет
Всего: 158



какой ReplaceDialog?! какие затирания?! smile

просто построчно читать лог, парсить строку и добавлять в БД. если лог обновляется во время обработки, то тупо сделать "маркер" обработанного...

fopen/fread, strchr/strstr/... либо аналоги.

Добавлено через 3 минуты и 28 секунд
практически все время в таком раскладе будет уходить на инсерты в бд...
PM MAIL   Вверх
RayR
Дата 24.5.2007, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 23.5.2007

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



Цитата(dumb @ 23.5.2007,  12:25)
просто построчно читать лог, парсить строку и добавлять в БД. 

fopen/fread, strchr/strstr/... либо аналоги.

практически все время в таком раскладе будет уходить на инсерты в бд...

Dumb, если не сложно, небольшой примерчик smile 

С указанными функциями ранее не сталкивался (такова специфика, работаю в основном с БД и математикой). Вот кусок лога:

1179253584.808    279 ip-адрес TCP_MISS/200 1739 GET http/://avt.foto.mail.ru/list/kapr/_avatarsmall имя_пользователя DIRECT/194.67.23.206 image/jpeg
1179253584.857    271 ip-адрес TCP_MISS/200 1667 GET http/://avt.foto.mail.ru/mail/abc44/_avatarsmall имя_пользователя DIRECT/194.67.23.13 image/jpeg
1179253584.880      5 ip-адрес TCP_MEM_HIT/200 1641 GET http/://avt.foto.mail.ru/mail/p.s.a/_avatarsmall имя_пользователя NONE/- image/jpeg
1179253584.978    260 ip-адрес TCP_MISS/200 1577 GET http/://avt.foto.mail.ru/mail/romul-avgustul/_avatarsmall имя_пользователя DIRECT/194.67.23.206 image/jpeg
1179253585.004    237 ip-адрес TCP_MISS/200 1015 GET http://status.mail.ru/? имя_пользователя DIRECT/194.67.23.104 image/gif

Нужно выделить IP и размер запроса (число перед ip.).

Это сообщение отредактировал(а) RayR - 24.5.2007, 12:00
PM MAIL   Вверх
dumb
Дата 24.5.2007, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: нет
Всего: 158



Цитата(RayR @  24.5.2007,  11:58 Найти цитируемый пост)
Dumb, если не сложно, небольшой примерчик


функция sscanf не самая быстрая, не самая безопасная, но для короткого примера - сойдет... smile
Код

#include <stdio.h>
unsigned int last_position = 0;
int GetLogLines()
{
  static char sb[4096];
  static char client_address[64], squid_result_code[64], request_method[64],
              url[1024], rfc931_ident[64], hierarchy_code[64], host[1024], type[64];
  int time, time_ms, duration, http_status, bytes;
  FILE *log = fopen("access.log", "r");
  if (!log) return -1;
  if (last_position) fseek(log, last_position, SEEK_SET);
  while (fgets(sb, sizeof(sb), log))
  {
    sscanf(sb, "%10d.%03d %6d %s %[A-Z_]/%03d %d %s %s %s %[A-Z_]/%s %s",
           &time, &time_ms, &duration, client_address, squid_result_code,
           &http_status, &bytes, request_method, url, rfc931_ident, hierarchy_code, host, type);
    //... работаем с полученными данными
  }
  last_position = ftell(log);
  fclose(log);
}


Цитата(RayR @  24.5.2007,  11:58 Найти цитируемый пост)
Нужно выделить IP и размер запроса (число перед ip.)

размер запроса в другом месте, а это время обработки...

PM MAIL   Вверх
chaos
Дата 25.5.2007, 15:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Серийный программист
****


Профиль
Группа: Завсегдатай
Сообщений: 2979
Регистрация: 7.7.2004
Где: Екатеринбург

Репутация: 2
Всего: 44



я обычно для такого дела использую boost::regexp
PM WWW   Вверх
dumb
Дата 26.5.2007, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: нет
Всего: 158



Цитата(chaos @  25.5.2007,  15:55 Найти цитируемый пост)
я обычно для такого дела использую boost::regexp

человеку, которому незнаком fopen, советовать буст и регэкспы я не решился. smile
PM MAIL   Вверх
RayR
Дата 28.5.2007, 08:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 23.5.2007

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



Большое спасибо за помощь!! 
Все получилось. Скорость обработки данных просто потрясающая - файл размером 180 метров "перекручивается за 2-3 минуты". 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C++: Базы данных"
chipset

Данный форум предназначен для обсуждения вопросов прямым образом связанных с C++ и БД. Так, вопросы только по C++ следует задавать в C++:Общие вопросы а вопросы по абстрактным БД в Базах данных или в соответствующих под-форумах.

Благодарим за понимание.


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

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Базы данных | Следующая тема »


 




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


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

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