Delphi создать файл если не существует

Обновлено: 04.07.2024

Когда речь идет о работе программы с текстовым файлом, подразумеваются процедуры ввода данных из файла в программу или, наоборот, запись этих данных в файл программой. Для текстового файла допустима простая работа с файлом без особых дополнительных механизмов, которые применяются для работы со специализированными файлами, такими как при загрузке данных из Excel или работе программы с базой данных. Разумеется, Delphi располагает возможностями работать с файлами с использованием компонентов. Но в данной статье рассматривается механизм прямой работы с текстовым файлом без использования дополнительных компонентов.

Итак, в общем виде, работа с файлом заключается в следующих этапах:

1. подключение к файлу – связь с внешним файлом, указание режима подключения;

2. выполнение операций записи в файл или чтения из файла;

3. завершение работы с файлом.

Подключение к файлу

Для связи программы с файлом используется специальная переменная – "Файловая переменная". Объявляется она так же как и любая переменная в Delphi. Тип это переменной может быть File для типизированных (хранящих данные определенного типа) файлов, а можно указать TextFile, что будет означать тип обычного текстового файла. Объявление переменной:

В исполняемом коде программы выполняется подключение к внешнему файлу:

Команда AssignFile, выполняет связь файловой переменной с внешним файлом. Вторым параметром указывается адрес файла. Он может быть задан относительным или абсолютным. Если указать только имя файла, то программа будет пытаться обнаружить его в той же директории, где она сама и находится. Абсолютный путь указывается от корневого диска:

Использование относительной директории дает возможность не привязываться к конкретным дискам и адресам. Например:

После того как выполнено подключение, выполняется процедура, устанавливающая режим работы с файлом. В основном это режим чтения или записи. Эти режимы назначаются процедурами Reset() ( для чтения) и rewrite() (для записи):

* Для команды Rewrite() следует учитывать, что при ее выполнении, она либо создает файл, указанный в файловой переменной, либо если он уже есть перезаписывает файл заново, удаляя старый без какого-то предупреждения.

Любую из указанных команд можно использовать без команды AssignFile(). Для этого достаточно вторым параметром указать путь к файлу. Таким образом, она сразу выполнит привязку файла к файловой переменной и назначит режим работы с этим файлом:

Операции с файлами

Для чтения из файла, необходимо назначить режим чтения и использовать команду Readln(), которая будет вводить в строковую переменную по одной строке из файла. Затем с этой переменой можно выполнить необходимые действия.

Обычно для загрузки всех строк из файла используется оператор цикла. Для того, чтобы определить, что файл закончился используется функция EOF() (End Of File). Таким образом получается цикл, в котором последовательно в строковую переменную вводятся все строки файла и завершающийся после окончания фала:

Для записи, назначение режим записи в файл и командой Writeln() производится запись по строкам.

Закрытие файла

По завершении работы с файлами, особенно в случае записи в них данных, необходимо корректно завершить работу с файловой переменной. Это делается для того, чтобы сохранить все внесенные в файл изменения.

Примеры работы с текстовыми файлами в Delphi

Чтение в переменную одного значения из файла:

Загрузить все строки файла в компонент Memo:

Следует отметить, что для этой задачи проще воспользоваться командой самого компонента Memo LoadFromFile().

Записать строку в файл:

Записать в текстовый файл все строки из компонента Memo:

Как и для чтения из файла в Memo, так и здесь, имеется специальная команда:

Работа с файлами важная вещь в любом языке программирования. Работа с файлами в Delphi позволяет считывать, сохранять информацию, и выполнять другие действия с файлами. В Delphi поддерживаются все операции с файлами - создание, поиск, чтение и запись, переименование как файлов, так и к директорий. В Delphi существует несколько способов работы с файлами.

Для "лирического" вступления нужно упомянуть компоненты Delphi, которые умеют работать с файлами. Они читают и сохраняют своё содержимое, строки типа String, в файл текстового формата. Это компоненты ListBox, ComboBox и Memo, расположенные на первой же вкладке палитры компонентов.

Каждая строка компонентов ListBox и ComboBox является объектом Items[i], а Memo - Lines[i], где i - номер строки, который отсчитывается от нуля. Добавление строк в компоненты выполняется методами Add и Insert:

Компоненты сохраняющие содержимое


begin
Memo1.Lines.Add('Первая строка');
ComboBox1.Items.Add('Первая строка');
ComboBox1.Items.Add('Вторая строка');
ListBox1.Items.Add('Первая строка');
ListBox1.Items.Add('Вторая строка');
end ;

Метод Add добавляет новую строку в конец. Метод Insert имеет дополнительный параметр, указывающий, после какой строки разместить новую строку. Доступ к строкам осуществляется так:

ComboBox1.Items[0] := 'Первая строка изменилась' ;
ListBox1.Items[1] := 'Вторая строка изменилась' ;

У компонента ComboBox дополнительно есть свойство Text, где (как и у компонента Edit) находится вводимый текст:

ComboBox1.Text := ' Вводимый текст ';

На выделенную в данный момент строку компонента ComboBox указывает свойство ItemIndex типа Integer, то есть это номер выделенной строки. Следовательно, получить саму выделенную строку компонента ComboBox можно следующей конструкцией:

или, пользуясь оператором присоединения

With ComboBox1 do
S:=Items[ItemIndex];

Вот как по нажатию клавиши Enter можно заносить в этот компонент вводимую в строку информацию и удалять нажатием Escape:
Выделите на Форме ComboBox и перейдите в Инспектор объектов, на вкладку Events. Щёлкните дважды по обработчику OnKeyPress. Система Delphi создаст заготовку обработчика. Напишите:

Ну а теперь собственно о сохранении содержимого в файл. Для этого выполните команду

ListBox1.Items.SaveToFile(' Имя_файла.txt ') ;

Впрочем, расширение можно поставить любое по желанию, не обязательно .txt, как и вообще без него обойтись. Но расширение .txt позволит легко открыть файл стандартным виндовским Блокнотом, что бывает очень удобно на этапе написания программы!
Для загрузки служит метод LoadFromFile:

ListBox1.Items.LoadFromFile(' Имя_файла.txt ') ;

Что делать, если в своей программе мы не работаем с компонентами Combobox, ListBox или Memo, а сохранять информацию нужно? Берём один из компонентов и делаем его невидимым, для этого в Инспекторе Объектов ставим в свойство Visible значение False. Функциональность его от этого не изменится!

Последний штрих - создадим программу, сохраняющую своё положение на экране в момент закрытия и там же открывающуюся. Нам нужно сохранить два параметра - значения свойств Формы Left и Top, это расстояние от левого и верхнего краёв экрана соответственно. Значения эти выражаются в пикселах и имеют тип Integer. Необходимо перевести эти числа в строку (тип String) с помощью оператора IntToStr. Итак, разместите на Форме невидимый ListBox, щёлкните по пустому месту Формы, чтобы её свйства появились в Инспекторе объектов, и перейдите на вкладку Events. Щёлкните по обработчику OnClose и в созданной заготовке напишите:

begin
ListBox1.Items.Clear;
ListBox1.Items.Add(IntToStr(Form1.Left));
ListBox1.Items.Add(IntToStr(Form1.Top));
ListBox1.Items.SaveToFile('MyFormPos.txt');
end ;

Этот обработчик сохраняет положение Формы на экране. Теперь напишем обработчик, помещающий Форму на прежнее место при старте программы. Создайте заготовку обработчика события OnCreate. Это событие происходит в момент "создания" Формы операционной системой. В этот момент и нужно присваивать ей необходимые свойства. Пишите:

begin
if FileExists('MyFormPos.txt') then
begin
ListBox1.Items.LoadFromFile('MyFormPos.txt');
Form1.Left:=StrToInt(ListBox1.Items[0]);
Form1.Top:=StrToInt(ListBox1.Items[1]);
end ;
end ;

В первой строке происходит проверка на существование файла, ведь если его не будет, произойдёт ошибка. Впрочем, программа после выдачи предупреждения откроется в том месте, где была на этапе проектирования, а при закрытии нужный файл будет воссоздан!
Затем в логических скобках begin / end содержится сам код, который будет выполнен только приналичии файла MyFormPos.txt в папке с программой, так как используется относительный путь. Можно указать конкретное местоположение, например, C:\Program Files\MyProg\MyFormPos.txt.

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

Конечно, профессиональные программы сохраняют своё положение в Реестре Windows. Но всему своё время.

Leha, добавлено 27.07.09, 09:30:54
Да. Великолепный пост. Добавил в мемориз. Mihan, добавлено 29.07.09, 08:24:43
Мда. Примерно тоже самое прочитал на севендей.ру. Уже много раз замечал. Такое ощущение, что они просто переписывают посты. Хотя. может меня и подглючивает . Автор, добавлено 29.07.09, 11:21:21
Робяты, ну никак понять не могу, почему все имена по-английски пишут!
Raven, добавлено 3.08.09, 14:49:46
Соглашусь с первым автором,и хочу сразу же задать вопрос.У меня в listbox выводится Имя а потом Номер в скобках тоесть вот так к примеру Елена(920*******) как сделать чтобы при нажатии на Елену в Edit записывался только номер Ответ, добавлено 3.08.09, 17:23:19
Можно вычислить номер символа "(" и скопировать текст от этого номера плюс один до номера символа ")" минус один. Как это делается, объяснять? Raven, добавлено 4.08.09, 11:10:38
Да объяснять=).Спасибо что ответили,я самоучка просто.Читаю книжку в данный момет библия для программиста в среде делфи,но пока ответа на свой вопрос там не нашел.Расскажите пожалуйста вы если не сложно.Заранее спасибо. Продолжаем разговор!, добавлено 4.08.09, 14:13:45
Нужно освоить работу со строками. Есть функция Pos, которая даёт позицию первого вхождения нужного символа. Копирование части строки производится функцией Copy. Вот как:

procedure TForm1.ListBox1Click(Sender: TObject);
var N1, N2, N3: Integer;
S: String;
begin
S:=ListBox1.Items[ListBox1.ItemIndex];
N1:=Pos('(', S); //Позиция символа (
N2:=Pos(')', S); //Позиция символа )
N3:=N2-N1; //Количество копируемых символов
Edit1.Text:=Copy(S, N1, N3);
end;

Memo1.Lines.Add('Первая строка');
ComboBox1.Items.Add('Первая строка');
ComboBox1.Items.Add('Вторая строка');
ListBox1.Items.Add('Первая строка');
ListBox1.Items.Add('Вторая строка');

Не вышло? Ринат, добавлено 26.07.11, 14:18:08
Все получилось.
спасибо а как сделать чтоб сразу появлялась? без нажатия кнопки? Автор, добавлено 26.07.11, 14:26:54
Я так понимаю, что Delphi вы впервые видите. Так вот, в Delphi ничего само по себе не появляется. Всё происходит при выполнении какого-либо события. Нажатие кнопки Button, или кнопки на клавиатуре, или кнопки мышки, момента появления Формы на экране, изменения текста в компоненте и т.д.

Так что вы имеете в виду под словом "сразу"? В самом начале, при появлении программы? Ринат, добавлено 26.07.11, 21:04:38
Да, вы правы, с программированием я столкнулся впервые.
Я имел ввиду при появление формы на экране. Автор, добавлено 26.07.11, 21:16:14
Появление Формы на экране - это события такого объекта, ну или компонента, как Форма. Посмотрите, щёлкнув по пустому месту на Форме, слева Инспектор Объектов, в него загружены свойства Формы. В Инспекторе Объектов две вкладки - Properties (свойства) и Properties (события). Так вот, те события, на которые может реагировать Форма, находятся на вкладке Properties. За появление Формы на экране отвечает событие OnActivate, хотя лучше всё же воспользоваться OnCreate - событием создания Формы. Поместите в обработчик этого события вышеуказанные операторы.

procedure TForm1.Button1Click(Sender: TObject);
begin
MP1.DeviceType:=dtAutoSelect;
MP1.FileName:='имя_файла';
if not MP1.AutoOpen then MP1.Open;
MP1.Play;
end;

AVI сейчас допишу. Саша, добавлено 10.11.11, 18:19:55
А для этого не надо добавлять какие-то компоненты наподобие таймера или ещё чего-то? Автор, добавлено 10.11.11, 18:41:07
Чтобы просто был звук - больше ничего не надо. Но если вы хотите создать полноценный плейер, то конечно придётся что-то придумывать.

procedure TForm1.Button2Click(Sender: TObject);
begin
MP1.Display:=Panel1;
with OpenDialog1 do
if Execute then
begin
MP1.FileName:=FileName;
MP1.Open;
MP1.Play;
end;
end;

Тут нужно добавить OpenDialog, можно и в предыдущий пример его вставить. И ещё. Размер области воспроизведения, то бишь панели, нужно посмотреть заранее в свойствах файла, на вкладке "Сведения". Но лучше сделать панель побольше, и установить её свойство BevelInner и BevelOuter в bvNone, чтобы её было не видно. А то размеры у файлов разные.

Что касается формата *.3ds, то я не умею работать с 3d видео. Цельная книжка есть про это. Но, блин, изучению надо жизнь посвятить. Но если с вас требуют лабораторку, то наверное преподавали.
Вот, нашёл что нужно иметь модуль GLFile3DS. Он необходим для работы с форматом 3DS. Саша, добавлено 10.11.11, 19:17:47
Спасибо огромное! А что касается *.3ds то как я разговаривал с преподом, то он сказал что надо только показать грудо говоря jpg (или какую-то ещё) проэкцию этого файла но не редактировать его. может тут не надо того модуля? Автор, добавлено 10.11.11, 19:19:09
Не смогу по 3ds подсказать ничего. Звиняйте.

А про avi ещё. Чтобы масштабировать изображение, нужно воспользоваться свойством медиаплейера DispleyRect. Оно доступно только программно. Саша, добавлено 15.11.11, 04:10:29
Я случайно заметил одну особенность: если не создавать панель (Panel1) и не присваивать панели ничего дисплею, то видео выводится в отдельном окне со своим родным расширением.

Но без вопроса не обойдётся =) : как настроить полосу прокрутки для видео или же хотя бы для аудио? Понятно что нужен таймер и и ProgresBar, но как связать это всё во едино? Автор, добавлено 15.11.11, 09:00:43
Когда файл открыт, то свойство Mediaplayer.Length возвращает продолжительность трека в специфическом формате. Лучше всего предварительно задать отображение этой величины в миллисекундах:

Ну далее переводим в часы, минуты и секунды с помощью функции

function taim(Length: Integer): String;
var chas, min, sec: Integer;
function mode(Length: Integer): String;
begin
Result:=IntToStr(Length);
if Length
Это что касается длины. А текущую позицию возвращает свойство. - правильно, Position! Измеряем по срабатыванию таймера и выводим в ProgressBar (лучше возьмите TrackBar). Опять же, свойство TrackBar.Max предварительно установите равным Mediaplayer.Length.

Есть проблемка с прокруткой. Чтобы прокрутить, нужно сначала остановить плеер, и таймер. А затем запустить с другим значением:

Я был удивлён, но TrackBar не имееет событий мыши. А то можно было бы останавливать по событию OnMouseDown. А впрочем, можно пользоваться событием OnEnter! Но запускать всё равно потом приходится.

А чтобы менять кадры при перемотке мышкой, придётся ввести второй таймер, чтобы работал когда воспроизведение останавливается, и задавал

MediaPlayer.Position:=TrackBar.Position;

Время срабатывания естественно сделать поменьше, а то будет тормозить.
Саша, добавлено 16.11.11, 18:59:41
Спасибо! =) Саша, добавлено 17.11.11, 01:24:40
Здравствуйте в очередной раз) Вот какая у меня проблема, когда открываю видео с помощью MedaiPlayer1, то функция Mediaplayer1.Length возвращяет уауое-то кривое значение (например продолжительность видео 40 мин. а возвращает значение примерно 1,17 мин.), но в случае с аудио файлами всё происходит нормально (то есть значение правильное). Но что самое интересное - видео проигрывается свыше возвращенного значения. В чём может быть дело? Автор, добавлено 17.11.11, 02:03:44
Странно. У меня фильм в программе определяется как 1 час 26 минут 55 секунд, с такой программой как Media Player Classic разница несущественная. Вот полный текст программы:

function taim(Length: Integer): String;
var chas, min, sec: Integer;
function mode(Length: Integer): String;
begin
Result:=IntToStr(Length);
if Length
Может вы забыли формат длительности задать? Я закомментировал этот оператор, и продолжительность вместо полутора часов стала две минуты. Саша, добавлено 17.11.11, 03:32:39
Нет, он описан в процедуре TForm1.FormCreate. Но после того, как я удалил его от туда и прописал отдельно для каждой кнопки вызова медиа плеера - всё встало на свои места) Так-что спасибо) Саша, добавлено 20.11.11, 21:56:43
Автор, большое Вам спасибо за этот прекрасный сайт а особенно за ваши ответы на задаваемые вопросы! Я закончил то задание с *.3ds форматом, но дело сдвинулось с мёртвой точки только после того, как Вы написали что нуден модуль GLFile3DS. Как оказалось - это не совсем "сам по себе" модуль) Это часть проекта GLScene. Советую Вам хотя бы не много им поинтересоваться. Полезная вещь. Ещё раз огромное Вам спасибо за помощь и поддержку в трудной ситуации!

ПС
Если надумаете всё таки заняться этим GLScene-ом - то хорошо ищите как правильно его устанавливать. Даже на оф. сайте инструкция не совсем точная. Андрей, добавлено 18.12.11, 02:33:53
помогите, не получается сохранить файл.
пишу такод код, файла нет, ошибок тоже нет:
procedure TForm1.N3Click(Sender: TObject);
begin
with SaveDialog1, Memo1 do
if Execute then
Lines.SaveToFile('ф.txt');
CloseFile(SaveF);
end; Автор, добавлено 18.12.11, 06:59:18
Зачем вам диалог, если вы сохраняете в файл 'ф.txt' - его и ищите. Андрей, добавлено 18.12.11, 11:17:05
если писать вместо ф.txt, FilEname, как в вашем уроке, то файл не сохраняется. Помогите, что я не так делаю. Автор, добавлено 18.12.11, 15:44:10
Вот написали бы именно как делаете, я бы посмотрел. А так приходится гадать. Может, вы Filename в кавычках пишете. Тогда файл будет называться не как в диалоге вы задали, а именно Filename.txt Владимир, добавлено 11.01.12, 23:19:26
Спасибо за уроки начал недавно но кое что уже получается. Изучение затеял с целью
написания электронных тестов для учеников по химии. Однако столкнулся с такой проблемой как на форме разместить например H2O но чтобы 2 была маленькой. Понимаю что вопрос не в тему и может быть не простой но интересует общее направление поиска, больше не кого спросить. Заранее спасибо. Автор, добавлено 12.01.12, 08:30:21
Владимир, вариантов масса. В зависимости от того, как конструктивно построен тест, на каких компонентах. Ведь можно три метки Label рядом стоящие, размер - любой. Или можно картинку нарисовать и поместить в нужное место - компонент Image, или даже просто по Форме написать, на её канве. Владимир, добавлено 12.01.12, 21:23:09
Спасибо буду пробовать. Александр, добавлено 1.05.12, 14:03:59
создал на форме все как положенно, с такимеже названиями.
в код после implementation вставил
begin
Memo1.Lines.Add('Первая строка');
ComboBox1.Items.Add('Первая строка');
ComboBox1.Items.Add('Вторая строка');
ListBox1.Items.Add('Первая строка');
ListBox1.Items.Add('Вторая строка');
end ;

но почему-то не работает, при запуске выдает ошибку Александр, добавлено 1.05.12, 15:31:21
аааааааа, надо по форме два раза щелкнуть и писать, понял!! Александр, добавлено 1.05.12, 17:11:13
выручайте.

написал через add все отлично, затем использовал команду Insert.

вылетает ошибка "Debugger exception notification Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 0056D0FD in modul 'Project1.exe'.Read of address 0000030C.Process stopped. Use Step or Run to continue."

Аноним, добавлено 1.05.12, 17:36:26
В ошибках разбираться недосуг. Вот как надо:

Memo1.Lines.Insert(0, 'Первая строка');
Александр, добавлено 1.05.12, 17:44:33
вы же в самом начале урока говорите что вот так:

ComboBox1.Items[0] := 'Первая строка изменилась' ;
ListBox1.Items[1] := 'Вторая строка изменилась' ;

я это копирю вставляю в программу и вылазит ошибка Александр, добавлено 1.05.12, 17:54:49
и не понятно почему


Вот поэтому рекомендуется использовать специализированный в Delphi объект TFiiestream. Вы можете написать и свой класс, который будет делать то же самое, но TFiiestream делает это достаточно хорошо.

СОВЕТ. Объект TFileStream рекомендуется использовать по следующей причине. Если Microsoft снова введет какие-то нововведения, Borland учтет их в объекте, и вам нужно будет только перекомпилировать свои программы. Никаких изменений в код вносить не надо. Вы один раз изменяете объект (или это делает Borland) и компили­руете все свои программы с новыми возможностями. Это громадное преимущество ООП, и вы должны его использовать, потому что оно упрощает жизнь.

У TFileStream есть еще одно преимущество — вам не нужно отслеживать ново­введения от Microsoft. В этой корпорации постоянно появляются новые идеи, из-за которых появляются новые функции, а мы, программисты, должны постоянно изу­чать новинки и переписывать код. Лично я намучился уже с функциями работы с файлами. Их так много, что с первого взгляда даже не поймешь, какие новые и рекомендуются к использованию, а какие устарели. В любом случае, использова­ние этого объекта намного проще, чем WinAPI, поэтому желательно начинать изу­чение работы с файлами именно с него.

Итак, давайте взглянем на объект TFileStream. Первое, что надо сделать, — это объявить какую-нибудь переменную типа TFileStream:

Вот так мы объявили переменную f типа объекта TFileStream. Теперь можно проинициапизировать переменную.

Инициализация — выделение памяти и установка значений по умолчанию. За эти действия отвечает метод create. Нужно просто вызвать его и результат выполнения присвоить переменной. Например, в нашем случае нужно вызвать TFileStream.create и результат записать в переменную f.

Давайте разберемся, какие параметры могут быть при инициализации объекта TFileStream. У метода create может быть три параметра, причем последний мож­но не указывать.

  • Имя файла (или полный путь к файлу), который надо открыть. Этот параметр — простая строка.
  • Режим открытия. Здесь вы можете указать один из следующих параметров открытия файла:
    • fmCreate— создать файл с указанным в первом параметре именем. Если файл уже существует, то он откроется в режиме для записи;
    • fmOpenRead — открыть файл только для чтения. Если файл не существует, то произойдет ошибка. Запись в файл в этом случае не возможна;
    • fmopenwrite — открыть файл для записи. При этом во время записи текущее содержимое уничтожается;
    • fmOpenReadWrite — открыть файл для редактирования (чтения и записи).
    • fmshareCompat — при этих правах другие приложения тоже имеют права ра­ботать с открытым файлом;
    • fmShareExciusive — другие приложения не смогут открыть файл;
      • fmShareDenyWrite — при данном режиме другие приложения не смогут от­крывать этот файл для записи. Файл может быть открыт только для чтения;
      • fmshareDenyRead— при данном режиме другие приложения не смогут от­крывать этот файл для чтения. Файл может быть открыт только для записи;
      • fmShareDenyNone — не мешать другим приложениям работать с файлом.

      С первыми двумя параметрами все ясно. Но зачем же нужны права доступа к файлам. Допустим, что вы открыли файл для записи. Потом его открыло другое приложение и тоже для записи. Обе программы записали какие-то данные. После этого ваше приложение закрыло файл и сохранило все изменения. Тут же другое приложение перезаписывает ваши изменения, даже не подозревая о том, что они уже прошли. Вот так ваша информация пропадает из файла, потому что другая программа просто перезаписала ее.

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

      После того как вы поработали с файлом, достаточно вызвать метод Free, чтобы закрыть его:

      Теперь давайте познакомимся с методами чтения, записи и внутренней структу­рой файла. Начнем со структуры. Когда вы открыли файл, позиция курсора уста­навливается в самое начало и любая попытка чтения или записи будет происходить в эту позицию курсора. Если вам надо прочитать или записать в любую другую по­зицию, то надо передвинуть курсор. Для этого есть метод seek. У него есть два па­раметра:

      • Число, указывающее на позицию, в которую надо перейти. Если вам нужно пе­редвинуться на 5 байт, то просто поставьте цифру 5.
      • Откуда надо двигаться. Тут возможны три варианта:
      • soFromBeginning — двигаться на указанное количество байт от начала файла.
        • soFromCurrent — двигаться на указанное количество байт от текущей пози­ции в файле к концу файла.
        • soFromEnd — двигаться от конца файла к началу на указанное количество байт.

        Не забывайте, что 1 байт— это один символ. Единственное исключение — файлы в формате Unicode. В них один символ занимает 2 байта. Так образом, надо учитывать, в каком виде хранится информация в файле.

        Итак, если вам надо передвинуться на 10 символов от начала файла, можете на­писать следующий код:

        Метод seek всегда возвращает смещение курсора от начала файла. Этим можно воспользоваться, чтобы узнать, где мы сейчас находимся, а можно и узнать общий размер файла. Если переместиться в конец файла, то функция вернет количество байт от начала до конца, т. е. полный размер файла.

        В следующем примере устанавливается позиция в файле на 0 байт от конца, т. е. в самый конец. Тем самым получается полный размер файла:

        Вот таким небольшим трюком можно узнать размер. Правда, для этого придется ис­пользовать три операции: открыть, переместиться в конец файла и потом закрыть его.

        Для чтения из файла нужно использовать метод Read. И снова у этого метода два параметра:

        • переменная, в которую будет записан результат чтения;
        • количество байт, которые надо прочитать.

        Давайте взглянем на код чтения из файла, начиная с 15-й позиции. Этот код вы можете увидеть в листинге

        f:TFileStream; //Переменная типа объект

        TFileStream. buf: array[0..10] of char; // Буфер для хранения прочитанных данных begin

        //В следующей строке я открываю файл filename.txt для чтения и записи,

        f:= TFileStream.Create(1 с:\filename.txt', fmOpenReadWrite);

        f.Seek(15, soFromCurrent); // Перемещаюсь на 15 символов вперед,

        f.Read(buf, 10); // Читаю 10 символов из установленной позиции.

        f.Free; // Уничтожаю объект и соответственно закрываю файл, end;

        Обратите внимание, что в методе seek движение происходит на 15 символов не от начала, а от текущей позиции, хотя нужно от начала. Это потому, что после от­крытия файла текущая позиция и есть начало. Но лучше на это не рассчитывать.

        Метод Read возвращает количество реально прочитанных байт (символов). Если не возникло никаких проблем, то это число должно быть равно количеству запро­шенных для чтения байт.

        Есть только два случая, когда эти числа отличаются:

        • при чтении был достигнут конец файла и дальнейшее чтение стало невозможным;
        • ошибка на диске или любая другая проблема.

        Осталось только разобраться с записью. Для этого мы будем использовать метод write. У него так же два параметра:

        • переменная, содержимое которой нужно записать;
        • число байт для записи.

        Пользоваться этим методом можно точно так же, как и методом для чтения.

        ЗАМЕЧАНИЕ. После чтения или записи текущая позиция в файле смещается на ко­личество прочитанных байт. То есть текущая позиция становится в конец прочитанно­го блока данных.

        Пример пока рассматривать не будем, потому что в принципе и так все ясно. А если есть вопросы, то на практике мы закрепим этот материал буквально через один или два раздела, когда будем работать со структурами.


        Вот поэтому рекомендуется использовать специализированный в Delphi объект TFiiestream. Вы можете написать и свой класс, который будет делать то же самое, но TFiiestream делает это достаточно хорошо.

        СОВЕТ. Объект TFileStream рекомендуется использовать по следующей причине. Если Microsoft снова введет какие-то нововведения, Borland учтет их в объекте, и вам нужно будет только перекомпилировать свои программы. Никаких изменений в код вносить не надо. Вы один раз изменяете объект (или это делает Borland) и компили­руете все свои программы с новыми возможностями. Это громадное преимущество ООП, и вы должны его использовать, потому что оно упрощает жизнь.

        У TFileStream есть еще одно преимущество — вам не нужно отслеживать ново­введения от Microsoft. В этой корпорации постоянно появляются новые идеи, из-за которых появляются новые функции, а мы, программисты, должны постоянно изу­чать новинки и переписывать код. Лично я намучился уже с функциями работы с файлами. Их так много, что с первого взгляда даже не поймешь, какие новые и рекомендуются к использованию, а какие устарели. В любом случае, использова­ние этого объекта намного проще, чем WinAPI, поэтому желательно начинать изу­чение работы с файлами именно с него.

        Итак, давайте взглянем на объект TFileStream. Первое, что надо сделать, — это объявить какую-нибудь переменную типа TFileStream:

        Вот так мы объявили переменную f типа объекта TFileStream. Теперь можно проинициапизировать переменную.

        Инициализация — выделение памяти и установка значений по умолчанию. За эти действия отвечает метод create. Нужно просто вызвать его и результат выполнения присвоить переменной. Например, в нашем случае нужно вызвать TFileStream.create и результат записать в переменную f.

        Давайте разберемся, какие параметры могут быть при инициализации объекта TFileStream. У метода create может быть три параметра, причем последний мож­но не указывать.

        • Имя файла (или полный путь к файлу), который надо открыть. Этот параметр — простая строка.
        • Режим открытия. Здесь вы можете указать один из следующих параметров открытия файла:
          • fmCreate— создать файл с указанным в первом параметре именем. Если файл уже существует, то он откроется в режиме для записи;
          • fmOpenRead — открыть файл только для чтения. Если файл не существует, то произойдет ошибка. Запись в файл в этом случае не возможна;
          • fmopenwrite — открыть файл для записи. При этом во время записи текущее содержимое уничтожается;
          • fmOpenReadWrite — открыть файл для редактирования (чтения и записи).
          • fmshareCompat — при этих правах другие приложения тоже имеют права ра­ботать с открытым файлом;
          • fmShareExciusive — другие приложения не смогут открыть файл;
            • fmShareDenyWrite — при данном режиме другие приложения не смогут от­крывать этот файл для записи. Файл может быть открыт только для чтения;
            • fmshareDenyRead— при данном режиме другие приложения не смогут от­крывать этот файл для чтения. Файл может быть открыт только для записи;
            • fmShareDenyNone — не мешать другим приложениям работать с файлом.

            С первыми двумя параметрами все ясно. Но зачем же нужны права доступа к файлам. Допустим, что вы открыли файл для записи. Потом его открыло другое приложение и тоже для записи. Обе программы записали какие-то данные. После этого ваше приложение закрыло файл и сохранило все изменения. Тут же другое приложение перезаписывает ваши изменения, даже не подозревая о том, что они уже прошли. Вот так ваша информация пропадает из файла, потому что другая программа просто перезаписала ее.

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

            После того как вы поработали с файлом, достаточно вызвать метод Free, чтобы закрыть его:

            Теперь давайте познакомимся с методами чтения, записи и внутренней структу­рой файла. Начнем со структуры. Когда вы открыли файл, позиция курсора уста­навливается в самое начало и любая попытка чтения или записи будет происходить в эту позицию курсора. Если вам надо прочитать или записать в любую другую по­зицию, то надо передвинуть курсор. Для этого есть метод seek. У него есть два па­раметра:

            • Число, указывающее на позицию, в которую надо перейти. Если вам нужно пе­редвинуться на 5 байт, то просто поставьте цифру 5.
            • Откуда надо двигаться. Тут возможны три варианта:
            • soFromBeginning — двигаться на указанное количество байт от начала файла.
              • soFromCurrent — двигаться на указанное количество байт от текущей пози­ции в файле к концу файла.
              • soFromEnd — двигаться от конца файла к началу на указанное количество байт.

              Не забывайте, что 1 байт— это один символ. Единственное исключение — файлы в формате Unicode. В них один символ занимает 2 байта. Так образом, надо учитывать, в каком виде хранится информация в файле.

              Итак, если вам надо передвинуться на 10 символов от начала файла, можете на­писать следующий код:

              Метод seek всегда возвращает смещение курсора от начала файла. Этим можно воспользоваться, чтобы узнать, где мы сейчас находимся, а можно и узнать общий размер файла. Если переместиться в конец файла, то функция вернет количество байт от начала до конца, т. е. полный размер файла.

              В следующем примере устанавливается позиция в файле на 0 байт от конца, т. е. в самый конец. Тем самым получается полный размер файла:

              Вот таким небольшим трюком можно узнать размер. Правда, для этого придется ис­пользовать три операции: открыть, переместиться в конец файла и потом закрыть его.

              Для чтения из файла нужно использовать метод Read. И снова у этого метода два параметра:

              • переменная, в которую будет записан результат чтения;
              • количество байт, которые надо прочитать.

              Давайте взглянем на код чтения из файла, начиная с 15-й позиции. Этот код вы можете увидеть в листинге

              f:TFileStream; //Переменная типа объект

              TFileStream. buf: array[0..10] of char; // Буфер для хранения прочитанных данных begin

              //В следующей строке я открываю файл filename.txt для чтения и записи,

              f:= TFileStream.Create(1 с:\filename.txt', fmOpenReadWrite);

              f.Seek(15, soFromCurrent); // Перемещаюсь на 15 символов вперед,

              f.Read(buf, 10); // Читаю 10 символов из установленной позиции.

              f.Free; // Уничтожаю объект и соответственно закрываю файл, end;

              Обратите внимание, что в методе seek движение происходит на 15 символов не от начала, а от текущей позиции, хотя нужно от начала. Это потому, что после от­крытия файла текущая позиция и есть начало. Но лучше на это не рассчитывать.

              Метод Read возвращает количество реально прочитанных байт (символов). Если не возникло никаких проблем, то это число должно быть равно количеству запро­шенных для чтения байт.

              Есть только два случая, когда эти числа отличаются:

              • при чтении был достигнут конец файла и дальнейшее чтение стало невозможным;
              • ошибка на диске или любая другая проблема.

              Осталось только разобраться с записью. Для этого мы будем использовать метод write. У него так же два параметра:

              • переменная, содержимое которой нужно записать;
              • число байт для записи.

              Пользоваться этим методом можно точно так же, как и методом для чтения.

              ЗАМЕЧАНИЕ. После чтения или записи текущая позиция в файле смещается на ко­личество прочитанных байт. То есть текущая позиция становится в конец прочитанно­го блока данных.

              Пример пока рассматривать не будем, потому что в принципе и так все ясно. А если есть вопросы, то на практике мы закрепим этот материал буквально через один или два раздела, когда будем работать со структурами.

              Читайте также: