Вот поэтому рекомендуется использовать специализированный в Delphi объект TFiiestream. Вы можете написать и свой класс, который будет делать то же самое, но TFiiestream делает это достаточно хорошо.
У TFileStream есть еще одно преимущество — вам не нужно отслеживать нововведения от Microsoft. В этой корпорации постоянно появляются новые идеи, из-за которых появляются новые функции, а мы, программисты, должны постоянно изучать новинки и переписывать код. Лично я намучился уже с функциями работы с файлами. Их так много, что с первого взгляда даже не поймешь, какие новые и рекомендуются к использованию, а какие устарели. В любом случае, использование этого объекта намного проще, чем WinAPI, поэтому желательно начинать изучение работы с файлами именно с него.
Итак, давайте взглянем на объект TFileStream. Первое, что надо сделать, — это объявить какую-нибудь переменную типа TFileStream:
var
f: 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-й позиции. Этот код вы можете увидеть в листинге
var
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. У него так же два параметра:
- переменная, содержимое которой нужно записать;
- число байт для записи.
Пользоваться этим методом можно точно так же, как и методом для чтения.
Пример пока рассматривать не будем, потому что в принципе и так все ясно. А если есть вопросы, то на практике мы закрепим этот материал буквально через один или два раздела, когда будем работать со структурами.