|
Вопрос # 3 425/ вопрос открыт / |
|
Здравствуйте, уважаемые эксперты!
Имеется текстовый файл описывающий сеансы связи, сеансы отделяются
друг от друга строкой, состоящей из звездочек.
Моя задача - организовать поиск и выводить в окошке конкретные сеансы.
Поскольку файл большой желательно организовать возможность поиска с
конца файла, но я не нашел в Дельфи средств как это сделать.
Также надо реализовать поиск по дате сеанса (то есть вытащить
информацию о дате из первой строки сеанса) и по одной из строк, но
чтобы результат поиска выводился посеансно, то есть между двумя
строками, состоящими из одних звездочек.
К сожалению все сеансы описываются разным количеством строк и могут
быть отделены друг от друга только строкой звездочек.
Кусочек файла для примера ниже прилагается.
К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса)
 |
Вопрос задал: Avtandil (статус: Посетитель)
Вопрос отправлен: 20 ноября 2009, 17:38
Состояние вопроса: открыт, ответов: 1.
|
Ответ #1. Отвечает эксперт: Вадим К
Здравствуйте, Avtandil!
я бы эту задачку решал так.
Вначале весь файл пробегается быстро и формируется индекс, куда записывается
- дата
- строка в файле
потом, когда надо найти по конкретной дате - смотрим в индекс, сразу знаем, где искать.
если надо найти какой файл был за какую дату скачан - просматриваем файл, ищем нужные подстроки, а потом по индексу восстанавливаем дату - надо найти такую запись, номер строки которой меньше заданной.
если это лог, который постоянно обновляется, то индекс можно просто "достраивать". смотрим в нашем индексе последюю строку, и начинаем парсить файл с этой строки и до конца.
Сам парсинг примитивный. ну где то так
line := 0;
assignfile(f, 'log.dat');
reset(f);
while not eof(f) do begin
readln(f, s);
inc(line);
if s = '********....***' then begin
readln(f, s); //тут у нас дата
inc(line);
//как то разбираем дату, добавляем в массив и\или индексный файл
end;
end;
CloseFile(f);
идея понятна?
При использовании индекса поиск будет очень быстрый.
Если непонятны детали - пишите что именно.
 |
Ответ отправил: Вадим К (статус: Академик)
Время отправки: 20 ноября 2009, 18:08
Оценка за ответ: 4
|
Мини-форум вопроса
Всего сообщений: 14; последнее сообщение — 23 ноября 2009, 14:25; участников в обсуждении: 3.
|
Мережников Андрей (статус: Абитуриент), 20 ноября 2009, 18:59 [#1]:
на одну дату один сеанс? или, все-таки, в первой строке дата-время сеанса? Насколько большой файл?
|
20 ноября 2009, 21:57: Вопрос перемещён из тематического раздела Delphi » Общие вопросы по программированию в раздел Delphi » Алгоритмы, преобразования модератором Ерёмин А.А.
|
Avtandil (статус: Посетитель), 20 ноября 2009, 23:36 [#2]:
>Мережников Андрей (статус: 8-ой класс), 20 ноября 2009, :18:59:
>на одну дату один сеанс? или, все-таки, в первой строке >дата-время сеанса? Насколько большой файл?
Выводить на экран посеансно, а сеанс каждый час, то есть на дату может быть около 30 сеансов, при поиске находим первый, а дальше просто прокрутка вперед.
Файл около 40 метров, но может быть до ста.
|
|
Avtandil (статус: Посетитель), 20 ноября 2009, 23:43 [#3]:
Вадим ! Спасибо за ответ. Вопрос в том как создать этот массив. Не хотелось бы организовывать новый файл. Можно ли это все делать в памяти при запуске программы ? И как вывести на экран результаты конкретного сеанса, если он удовлетворяет условию поиска по дате либо по имени файла ?
|
|
Вадим К (статус: Академик), 21 ноября 2009, 02:26 [#4]:
всё зависит от размера файла. Может индекс можно и в памяти держать.
второй вопрос)
находим номер строки, где есть нужный файл. Потом по индексу проходим от начала до тех пор, пока номер строки с файлом не станет меньше номера строки в индексе. После этого возвращаемся по индексу один раз назад.
теперь можно вырезать кусок лога, где нужный сеанс.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Мережников Андрей (статус: Абитуриент), 21 ноября 2009, 07:15 [#5]:
в качестве индекса можно попробовать использовать TStringList, если в него записывать только информацию, которую предлагает Вадим К. Так проще, на мой взгляд, будет организовать поиск. Например записывать дату и номер строки как пару "Имя-значение" (Name - Values).
|
|
Avtandil (статус: Посетитель), 21 ноября 2009, 08:57 [#6]:
Вадим, Андрей, спасибо за советы. Буду пробовать TStringList.
А как потом можно организовать переход к нужной строке, только n раз Readln? Вот есть компонент FindDlg, так там реализован поиск в обратном направлении, как это можно реализовать в случае с индексами ?
|
|
Вадим К (статус: Академик), 21 ноября 2009, 14:48 [#7]:
1) в данном случае я даже не знаю, как красиво использовать TStringList (не, код я с ним напишу, но мне будет стыдно за него). Я бы лично сделал так (это только заготовок классов!!!)
type
TRec = class
public
property number:integer;
property DateTime:TDateTime;
procedure Show;
end;
TIndex = class
private
List:TList;
public
procedure Add(nunmber:integer; db:TDateTime);
function FindByLine(number:Integer):integer;
procedure LoadFromFile(filename:string);
property Count:integer;
property Items[index:integer]:TRec; default;
end;
и теперь например реальный код
var ind:TIndex;
begin
ind := TIndex.Create;
ind.LoadFromFile('test.dat');
for i:= 0 to ind.Coount - 1 do
ind[i].Show;
ind.free;
Интересно?
2) переход к нужной строке. то есть вычитать нужную строку? да, можно просто отсчитать нужное кол-во readln в пустом цикле. Но у нас же индекс! кто нам мешает хранить позицию символьную, тогда с помощью FilePos можно узнать текущую позицию в файле при составлении индекса, а когда надо перейти туда, то всего одной функцией Seek. правда последняя функция не работает с текстовыми файлами, но разве нас это остановит??? Никто не мешает открыть его как типизированный...
3) Цитата (Avtandil):
FindDlg, так там реализован поиск в обратном направлении
А кто Вас сказал, что он там "реализован". его там нет. А как можно написать - я уже писал. Если это поиск файлов - то просто вначале пробегаем по файлу в прямом направлении, составляем список подходящий элементов, а далее, что хотим, то и делаем с ним. Вот только если файл уж слишком большой. Хотя я думаю, что Вы просто не знаете, что такое большой файл. вот у меня файлы лога легко могут быть по 2 гигабайта (когда я отлаживаю какие то специфичные моменты). и это нормально, я в них нахожу всё что надо.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Avtandil (статус: Посетитель), 22 ноября 2009, 13:38 [#8]:
Вадим !
К сожалению я не очень силен в Дельфи, так что мне надо немного подробнее разжевать 
Вот сейчас изучаю вашу статью о виртуальном ListView, это можно приспособить для первичного прогона файла и индексирования ? И если можно немного подробнее о индексах. Спасибо !
а файл у меня порядка 35 метров.
|
|
Вадим К (статус: Академик), 22 ноября 2009, 22:23 [#9]:
в статье есть интересные вещи. но не надо никогда смешивать визуальные компоненты и обработку. Это ужасно.
А что о индексах хочется узнать?
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Avtandil (статус: Посетитель), 23 ноября 2009, 10:11 [#10]:
ну вот хотя бы применимо к моей задаче - как их загнать в память (при соблюдении условия - что в строке звездочки), как к определенному индексу потом получить доступ. и как все это оптимизировать.
|
|
Вадим К (статус: Академик), 23 ноября 2009, 11:15 [#11]:
Мне что, полностью писать код?
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Avtandil (статус: Посетитель), 23 ноября 2009, 12:55 [#12]:
Хорошо бы было в виде статьи они у вас достаточно подробные и там можно рассмотреть все основные случаи с примерами. Как вот например есть статья о работе с файлами, так же с про индексы сделать - как с ними работать в различных компонентах.
|
|
Вадим К (статус: Академик), 23 ноября 2009, 13:41 [#13]:
не надо смешивать компоненты и индексы. Одно другому не мешает. оно просто параллельно.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Avtandil (статус: Посетитель), 23 ноября 2009, 14:25 [#14]:
Вот блин тут то мне знаний и не хватает...
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|