Построчный парсинг
Привет. Сегодня хочу рассмотреть построчную работу с файлом. Использовать будем стандартный паскалевский ввод/вывод: writeln и readln.
Например, перед нами задача: убрать от одного до десяти первых символов в каждой строке. Кстати, передо мной эта задача вчера реально встала, и я написал программу за 5 минут. Теперь и мы с тобой рассмотрим процесс написания.
Итак, сегодня будем писать со всеми прелестями delphi, читай с формой. Соорудим форму, поставим Edit1 и Edit2. Поставим OpenDialog1 и SaveDialog1, да и две кнопки для выбора файла в придачу.
Как это всё связать, думаю тебе известно. Но на всякий случай:
procedure TForm1.SpeedButton1Click(Sender: TObject); begin if OpenDialog1.Execute then Edit1.Text:=OpenDialog1.FileName; end; procedure TForm1.SpeedButton2Click(Sender: TObject); begin if SaveDialog1.Execute then Edit2.Text:=SaveDialog1.FileName; end;
Переназывать компоненты не станем.
Теперь нам нужно сделать выбор количества — от 1 до 10 символов (на выбор). Для этого я решил поставить TrackBar и Label так, что при изменении значения TrackBar менялось значение Label (от 1 до 10).
Вот так выглядит моя форма:
Теперь непосредственно парсинг:
procedure TForm1.SpeedButton3Click(Sender: TObject); var f, o: TextFile; s: string; c: integer; begin c:=TrackBar1.Position; if not FileExists(Edit1.Text) then begin ShowMessage('file not found'); Exit; end; AssignFile(f, Edit1.Text); AssignFile(o, Edit1.Text); Reset(f); Rewrite(o); repeat Readln(f, s); Delete(s, 1, c); Writeln(o, s); until Eof(f); CloseFile(f); CloseFile(o); ShowMessage('ready!'); end;
Как видишь, мы объявили две переменные типа TextFile, строку, которую используем как буфер, и переменную c, в которую записываем количество символов, указанное в TrackBar1.
Теперь теоретическая часть.
Работа с текстовыми файлами
Чтобы связать переменную типа TextFile (или просто text) с конкретным файлом, мы используем процедуру AssignFile (аналог в паскале — assign). Первый параметр — переменная типа TextFile (частный случай file), вторая — адрес файла.
Теперь мы хотим определиться, что же мы собираемся делать с файлом: читать из него, или писать в него? Если читать, надо использовать процедуру Reset с единственным параметром — нашей переменной типа TextFile.
А если мы планируем писать в файл, нам нужна похожая процедура Rewrite. Но учти, что она стирает файл полностью, тем самым мы будем писать с чистого листа. Если файла нет, то она его создаст. Есть также процедура Append, которая открывает на запись, но не стирает, то есть мы можем дописывать в конец файла.
Также следует сказать про функцию Eof, которой мы также передаём TextFile. Она возвращает True только тогда, когда мы своим чтением достигли конца файла. Тем самым для построчного парсинга идеально подходит цикл repeat until.
Построчный ввод и вывод: нет ничего проще! ReadLn — читаем строчку, WriteLn — пишем. Естественно, для соответственно открытых файлов.
Процедура CloseFile закрывает файл, открытый нами с помощью Reset, Rewrite или Append. Однако наша переменная всё еще связано с адресом файла, и мы можем заново открыть на ввод/вывод без использования такого же AssignFile.
Процедура Delete
Процедура Delete удаляет из строки её часть. Синтаксис:
procedure Delete(var S: string; Index, Count: integer);
Передаём процедуре строку, место, с которого начинать удаление (Index), и количество символов для удаления.
Ну вот и всё на сегодня, скачать проект можешь по ссылке.
И, конечно, постовой. Если ты вдруг захотел прочитать про деньги, SEO и раскрутку, то заходи на блог iZombie.ru.
Файлики — это классная штука, частенько с ними работаю. Только я, например, цикл repeat редко использую, чаще всего пишу так:
Мне кажется, что так проще. :-)
Я изначально преимущественно использовал repeat .. until, привык к нему. Мне в нём привлекает то, что я until ни с каким end не перепутаешь, и всегда видно, где кончается тело цикла
В цикле while есть один плюс в данном случае — если файло пустое, то тело цикла не выполнится ни разу, а с репитом — 1 раз пройдет точно :)
Согласен, спасибо :) И тогда будет в выходящем файле одна пустая строка
В своё время, разбираясь с текстовыми файлами я выяснил, что Writeln может выводить не только в файл, но и куда душа пожелает. В Memo, в интернет (на какой-нибудь блог) или на принтер. Вывод на принтер — стандартный модуль Printers. Мой модуль для вывода в Memo лежит в кладовке:
http://kladovka.net.ru/index.cgi?pid=viewprofile&rid=900
Как здорово, не знал ни про принтер, ни про TMemo, ни про интернет :)
Спасибо за модуль, Наиль
Со времён Pascal первой версии в Delphi перекочевали две переменные Input и Output.
Когда мы пишем
Writeln(X);
, т.е. не указываем файл явно, то компилятор понимает эту строку так:Writeln(Output, X);
Output — текстовый файл связный со стандартным выводом.
Это можно использовать для следующего хака:
Заменив
AssignFile(o, Edit1.Text);
наAssignFile(Output, Edit1.Text);
можно отказаться от переменой O — указывать файл во Writeln уже не нужно.Для консольных программ без хака стандартный вывод можно перенаправить в файл с помощью средств ОС.
Если в консольной программе program.exe написано
Writeln(X);
, то результат можно отправить в файл logfile.txt так:program.exe >logfile.txt
Зато, если в программе написано
AssignFile(o, 'con');
, тоWriteln(O, X)
будет выводить сообщения только на экран игнорируя перенаправление стандартного вывода, т.е. передать сообщения от такой консольной программы в файл или другой программе станет невозможно.Writeln — это очень мощный и загадочный инструмент, который достоин более пристального взгляда, чем то, что пишут в книгах.
Попробуйте догадаться, что выведут на экран следующие команды для разных X:=10.25; X:=’Aaa’; X:=10;
Writeln(X:10);
Writeln(X:10:2);
Writeln(X:2:10);
Последние две команды выдают ошибку для целочисленного и строкового типа (delphi 7). Последняя команда интересная, я так понимаю, что если место, отведённое, под вывод ( :2 ), меньше, чем количество знаков после запятой, оно просто игнорируется, так?
Использование переменной Output очень удобно, по аналогии попробовал с Input — теперь в обычных приложениях буду именно так файлы читать :)
это работает!!
>> ShowMessage(‘ready!’);
Лучше написать «Done! «, ибо «ready» — это больше готовность к чему-либо, но никак не завершение (конечно на работоспособности это никак не отражается:))
П.С. заметил небольшой баг в шаблоне: http://s003.radikal.ru/i203/1001/22/88061f0b7598.png
браузер Google Chrome, возможно из-за того что надпись «pub» слишком короткая.
Это языковой вопрос, думаю, ты прав. По поводу глюка, сделал надпись длиннее, теперь нормально, спасибо :)
Мне бы сначала паскаль нормально изучить :-) Потому уже Delphi буду покорять.
Эти методы подойдут и для Паскаля. Поэтому стоит приглядеться. А вообще можно смело начинать изучать Delphi.
Вместо ReadLn и тд лучше курить в сторону Windows API. Оно и работает быстрее и полезнее для программиста — можно применить не только в дельфи.
WinApi курить надо неспеша :)
Обязательно курну в одном из следующих постов, давно собираюсь
WinAPI классная штука, действительно. Ждем следующего поста про WinAPI. :-)
WinAPI хорошая вещь, хотелось бы получить больше информации.
Автор, в строке 13 и в листинге исходного кода программы и в архиве ошибка.
в тексте должно быть Edit2, а не Edit1
фрагмент как должно быть:
AssignFile(f, Edit1.Text);
AssignFile(o, Edit2.Text);
Reset(f); Rewrite(o);
сейчас:
AssignFile(f, Edit1.Text);
AssignFile(o, Edit1.Text);
Reset(f); Rewrite(o);
Спасибо за поправку, моё недоразумение)
Да кстати, исправь в исходниках. А тоя сначала не вкурил почему не пашет.
Эх… не так давно на подобный код у меня ушло почти пол дня :) Хотя лет 5-7 назад на дельфике даже что то мелкое на заказ писал :) Склероз вообщем
Для консольных программ без хака стандартный вывод можно перенаправить в файл с помощью средств ОС
Простите за вопрос не в тему…
а сколько будет стоить написать парсер (либо спарсить базу)???
К примеру база резюме и вакансий.
что бы потом это все добро можно было прямо в базу данных залить. =)
Прощаю :)
В данный момент не пишу ничего на заказ, времени нет
Подскажите, как спарсить url видео потоков с сайта онлайн тв?
Спасибо за статью.