|
||||||||
§13. Нетипизированные файлы. Подпрограммы для работы с файлами. Нетипизированные файлы. Работа с нетипизированными файлами во многом схожа с работой с типизированными файлами. Разница в том, что в нетипизированном файле тип данных не объявляется, поэтому в какую переменную вы считаете данные из файла тот тип и получите, а так же какую переменную впишите в файл, столько байт вы и займёте в файле. Для работы с нетипизированными файлами используются те же процедуры и функции, что и с типизированными. Так же есть указатель, который перемещается по файлу с шагом в один байт, и который можно устанавливать в любое место. Однако если вы считаете данные в переменную, которая занимает 2 байта, то указатель переместиться не на одну позицию, как в типизированном файле, а на две позиции и наоборот, если запишите переменную, занимающую 2 байта, то указатель тоже переместиться на две позиции. Суть нетипизированного файла заключается в том, что вы можете вписывать в файл данные разных типов, соответственно можно и считывать из файла данные разных типов. При этом настоятельно рекомендую следить за тем, какие данные, и в какой последовательности были вписаны в файл. В такой же последовательности и такие же данные необходимо будет извлекать оттуда. Пример: var f:file; s:string; b:integer; r:real; begin assign(f,'c:\file.dat'); rewrite(f); write(f,'Иван'); write(f,'Иванович'); write(f,'Иванов'); Write(f,30); Write(f,'Помощник директора'); Write(f,35600.35); close(f); reset(f); read(f,s); Writeln(' Имя - ',s); read(f,s); Writeln(' Отчество - ',s); read(f,s); Writeln(' Фамилия - ',s); read(f,b); Writeln(' Возраст - ',b,' лет'); read(f,s); writeln('Должность - ',s); read(f,r); Writeln(' Доход - ',r,' рублей в месяц'); close(f); end. ________________________________________________ Имя - Иван Отчество - Иванович Фамилия - Иванов Возраст - 30 лет Должность - Помощник директора Доход - 35600.35 рублей в месяц Как видно, структура созданного файла очень похожа на тип данных запись. Однако есть разнице. В данном примере мы вписываем в файл строки переменной длины, что не возможно было бы реализовать, используя тип данных запись. Тем самым мы можем сэкономить значительное количество памяти. К тому же, далее мы можем вписывать в файл ещё какие либо не повторяющиеся данные. Ещё раз повторюсь, следите за тем какие данные, в какой последовательности были вписаны в файл. Так же их и придётся извлекать оттуда. Если вы что то перепутаете, то может произойти ошибка ввода вывода. Поэтому вся ответственность за соответствие данных при работе с нетипизированными файлами лежит полностью на программисте. Далее приведу процедуры и функции которыми можно работать с нетипизированными файлами, примеры приводить не буду так как тут всё аналогично типизированным файлам, только помните, что файловый указатель перемещается с шагом в один байт. function Eof(f: FileType): boolean; – Возвращает True, если достигнут конец файла f. procedure Truncate(f: file); – Усекает нетипизированный файл f, отбрасывая все элементы с позиции файлового указателя. function FileSize(f: file): LongInt; – Возвращает количество байт в нетипизированном файле f. function FilePos(f: file): LongInt; – Возвращает текущую позицию файлового указателя в нетипизированном файле f. procedure Seek(f: file; n: LongInt); – Устанавливает текущую позицию файлового указателя в нетипизированном файле f на байт с номером n. Небольшое отступление. Всё то, что было написано выше во всех параграфах справедливо к языку Pascal в целом, т.е. эти знания вы можете применять как в среде разработки PascalABC.NET, так и в TurboPascal. То что было сказано выше про нетипизированные файлы справедливо только в среде программирования PascalABC.NET. В изначальном варианте Паскаля, в TurboPascal, работа с нетипизированными файлами организована несколько иначе. И кроме того был ещё один смысл их использования – это скоростной обмен данными между жёстким диском и оперативной памятью. Напомню, среда программирования PascalABC.NET была создана для обучения принципам программирования. Она ориентирована на программирование под операционную систему Windows. Поэтому PascalABC.NET отличается от «изначального» TurboPascal. В данном учебнике за основу был выбран язык PascalABC.NET, поэтому раскрывать принципы работы с нетипизированными файлами, которые заложены в TurboPascal в рамках данного учебника я не буду. Думаю, если вы обучаетесь в TurboPascal, то наверняка вы читаете параллельно и другую соответствующую литературу. Следовательно, в ней вы и узнаете про то, как реализована работа с нетипизированными файлами в TurboPascal. Так же в данном месте учебника хочется сделать ещё одно отступление и поговорить о том, как с помощью нетипизированного файла можно определить структуру переменной типа String. Строка может быть различного размера, соответственно и количество занимаемой ей памяти может быть разное. Поэтому, на мой взгляд, узнать, каким образом храниться переменная типа String в памяти компьютера, будет интересно. Сделать это можно следующим образом: запишем переменную типа String в нетипизированный файл, затем откроем этот файл как типизированный и выведем его на экран в виде последовательности байтов. Потом проанализируем эту последовательность. Далее код программы реализующей вышесказанное: var fnet:file; fbyte:file of byte; s:string; b:byte;
begin s:='АБВГД'; Assign(fnet,'c:\Exp.str'); Rewrite(fnet); write(fnet,s); Close(fnet); Assign(fbyte,'c:\Exp.str'); Reset(fbyte); while not Eof(fbyte) do begin read(fbyte,b); write(b,' '); end; Close(fbyte); end. _________________________________ 5 192 193 194 195 196 Проанализировав результат работы программы, можно придти к следующим умозаключениям: данная переменная занимает всего 6 байт памяти. Первый байт содержит количество символов в строке, последующие байты являются символами. Для проверки такого утверждения допишем в программу следующий код: ......................... writeln; Reset(fbyte); read(fbyte,b); write(b,' '); while not Eof(fbyte) do begin read(fbyte,b); write(Chr(b):3,' '); end; Close(fbyte); end. _____________________________ 5 192 193 194 195 196 5 А Б В Г Д Как видно из результата, наши рассуждения были верны. Получается, что в PascalABC.NET переменная типа String в памяти храниться следующим образом: первый байт содержит количество символов в строке, последующие байты содержат символы строки. Для чего я привёл данное отступление? Этим самым мне хотелось показать, что познавать программирование можно не только, читая справочную информацию и какую-либо литературу, но и проводя какие-либо эксперименты и опыты. Причём такой способ, может быть, и не всегда экономичен с точки зрения затраченного времени, тем не менее, он больше развивает ваш интеллект. Плюсом ко всему та информация, которая добыта вами в результате каких-либо опытов, лучше запоминается и будет лучше вами понята. Подводя итог к вышесказанному, хочется сказать следующее: на каждый, пройденный вами материал, придумывайте свои примеры программ и экспериментируйте над ними. Такой способ обучения даёт наилучшие результаты. Подпрограммы для работы с файлами. Далее будут приведены ещё ряд процедур и функций для работы с файлами, каталогами и дисками. Все они применимы ко всем трём типам файлов. procedure Erase(f: FileType); Удаляет файл, связанный с файловой переменной f. При использовании данной процедуры удаляемый файл не должен быть открыт, или использоваться другой программой: var f:file of Byte; begin assign(f,'c:\123.int'); erase(f); end. Функции для работы с именами файлов: procedure Rename(f: FileType; newname: string); – переименовывает файл, связанный с файловой переменной f, давая ему новое имя, находящееся в строке newname. При использовании данной процедуры так же переименовываемый файл не должен быть открыт, или использоваться другой программой: var f:file of Byte; begin assign(f,'c:\123.int'); rename(f,'c:\124.int'); end. function ExtractFileName(fname: string): string; – выделяет имя файла из полного имени файла fname. function ExtractFileExt(fname: string): string; – выделяет расширение из полного имени файла fname. function ExtractFilePath(fname: string): string; – выделяет путь из полного имени файла fname. function ExtractFileDir(fname: string): string; – выделяет имя диска и путь из полного имени файла fname. Пример программы с данными функциями: var s:string; begin s:='c:\Papka_1\Papka_2\file.dat'; writeln('Полное имя файла - ',s); writeln('ExtractFileName(s) - ',ExtractFileName(s)); writeln('ExtractFileExt(s) - ',ExtractFileExt(s)); writeln('ExtractFilePath(s) - ',ExtractFilePath(s)); writeln('ExtractFileDir(s) - ',ExtractFileDir(s)); end. _______________________________________________________ Полное имя файла - c:\Papka_1\Papka_2\file.dat ExtractFileName(s) - file.dat ExtractFileExt(s) - .dat ExtractFilePath(s) - c:\Papka_1\Papka_2\ ExtractFileDir(s) - c:\Papka_1\Papka_2 Процедуры и функции для работы с файлами, каталогами и дисками. function GetDir: string; – возвращает текущий каталог. procedure ChDir(s: string); – меняет текущий каталог. function SetCurrentDir(s: string): boolean; – Устанавливает текущий каталог. Возвращает True, если каталог успешно установлен. При указании имени файла можно указывать его без пути. В таком случае файл будет искаться в текущем каталоге. Изначально текущим каталогом считается тот каталог, в котором находится сама программа. О том, где находится та программа, которую вы написали и запустили на выполнение, будет рассказано в 18 параграфе. Сейчас просто знайте, если необходимо создать в программе файл, можете указать только его имя. Кстати с помощью функции GetDir можете узнать, где находится ваша программа: begin writeln('Эта программа находится в ',GetDir); writeln('Теперь сменим текущий каталог на C:\Program Files'); ChDir('C:\Program Files'); writeln('Уточняем, какой текущий каталог на данный момент - ',GetDir); end. ________________________________________________________________________ Эта программа находится в C:\PABCWork.NET Теперь сменим текущий каталог на C:\Program Files Уточняем, какой текущий каталог на данный момент - C:\Program Files function ChangeFileNameExtension(name,newext: string): string; – Изменяет расширение файла с именем name на newext. Другими словами, функция возвращает имя файла name с изменённым расширением на newext. Пример: var s:string; begin s:=ChangeFileNameExtension('c:\Exp.str','dat'); writeln(s); end. ___________________________________________________ c:\Exp.dat Следующие подпрограммы будут приведены без примеров. Думаю, вы без труда сможете с ними разобраться. Примеры их использования будет предложено создать самостоятельно в задачах для самостоятельного решения. procedure MkDir(s: string); – создает каталог. function CreateDir(s: string): boolean; – создает каталог. Возвращает True, если каталог успешно создан. procedure RmDir(s: string); – удаляет каталог. function RemoveDir(s: string): boolean; – Удаляет каталог. Возвращает True, если каталог успешно удален. function DeleteFile(s: string): boolean; – удаляет файл. Если файл не может быть удален, то возвращает False. function FileExists(name: string): boolean; – Возвращает True, если файл с именем name существует. Прежде чем открывать какой-либо файл, с помощью данной функции можно убедиться function DiskFree(diskname: string):LongInt; – Возвращает свободное место в байтах на диске с именем diskname. function DiskSize(diskname: string):LongInt; Возвращает размер в байтах на диске с именем diskname. function DiskFree(disk: integer):LongInt; – Возвращает свободное место в байтах на диске disk. function DiskSize(disk: integer):LongInt; – Возвращает размер в байтах на диске disk. В обоих последних функциях: disk=0 – текущий диск, disk=1 – диск A, disk=2 – диск B, и т.д. На этом изучение файлов закончено. Теперь у вас достаточно знаний для реализации большинства задач, связанных с ними. Единственное чего нельзя сделать – это прочитать содержимое диска. Т.е. можно работать, только с заранее известными или созданными в программе файлами. Что бы просмотреть имеющиеся файлы на диске и выбрать из них нужные, пройденных знаний ещё не достаточно. В рамках данной книги эти знания даны не будут т.к. системных подпрограмм для этого нет, а изучение материала, связанного с этим, не входит в рамки данного учебника. Тем не менее, думаю, что и без этого в учебнике хватит для вас информации. В данном параграфе мы познакомились с нетипизированными файлами и познакомились с системными подпрограммами для работы с файлами. Задачи. 1. В данном параграфе было показано, каким образом переменная типа String храниться в памяти компьютера. Создать программу, демонстрирующую данный принцип. В программе необходимо сформировать нетипизированный файл переменными типа String. Затем нужно вывести содержимое файла на экран в виде таблицы: в первом столбце должно находиться количество символов в строке, во втором столбце содержимое строки. Примечание: Строки можно сформировать случайным образом, с помощью функции random. 2. В параграфе был приведён ряд подпрограмм для работы с файлами без примеров их использования. Написать программы, демонстрирующие работу этих подпрограмм. Решение. 1. Program StrukturaString; //Программа демонстрирует структуру переменных типа String Var f:file; i,k:byte; sTemp:string; cTemp:char; begin assign(f,'c:\Text.ntf'); rewrite(f); //Формируем нетипизированный файл случайными строками For i:=1 to random(20) do begin sTemp:=''; //Формируем строку for k:=1 to random(20) do sTemp:=sTemp+chr(random(32,255)); Write(f,sTemp); end; close(f); //Выводим содержимое файла на экран Writeln('Количество символов Содиржимое строки'); reset(f); while not eof(f) do begin read(f,i); //Выводим количесвто символов write(i:19,' '); //Выводим содержимое строки for k:=1 to i do begin read(f,cTemp); write(cTemp); end; writeln; end; close(f); end. _______________________________________________________________________ Количество символов Содиржимое строки 16 Я$‹*ъ®†њћMсдШ.Ж2 11 юЖ‚x*Jv‰єжљ 15 (щ<л}7ЭѓOњu>©Yх 18 †;vbЄљMLд~ФЪ4Ў_ИмУ 10 SФш{чи®n‚q 6 ПСTѓ"џ 2. Данную задачу решите самостоятельно.
|