Саммерфилд - Программирование на Python 3 (1077331), страница 84
Текст из файла (страница 84)
В!кебтосК, хранящий коллекцию объектов В[КеБтосК. Взхе в виде записей в объекте ВзлагуйесогбЕ1)е. Втпа гуйесо гсЕ!)е. Универсальный класс В1лагуйесогдй!е Своим прикладным интерфейсом класс 81пагулесогСЕз)е. 81пагулесогаЕ1)е напоминает список, так как он обеспечивает возможность получения/добавления/удаления записи по заданному номеру позиции. Когда запись удаляется, она просто помечается как «удаленная», благодаря этому исчезает необходимость перемещать все последующие записи, чтобы заполнить промежуток; что также означает, что после удаления все первоначальные индексы остаются допустимыми. Другое преимущество такого подхода состоит в том, что запись легко может быть восстановлена, достаточно лишь убрать метку. Однако при таком подходе, удаляя записи, мы не можем экономить дисковое пространство.
Эта проблема будет решаться за счет методов «уплотнения» файла, которые будут ликвидировать удаленные записи (и соответственно будут изменяться номера позиций записей). Прежде чем приступить к рассмотрению реализации, взглянем на типичный пример использования: сор!асс = атгсст.бтгьст["<15в1") ссстаств = Взпагувессгсез)е.8«вагуаассгсе!!е(гз)есаве, состас! азха) Здесь создается структура (с обратным порядком следования байтов, 18-байтовая строка байтов н 4-байтовое целое число со знаком), которая будет представлять записи. Затем создается экземпляр класса ВзпагуйесогЬЕ!)е, 81лагуйесогоЕ11е, которому передается имя файла и размер записи, соответствующий размеру используемой структуры.
Если файл уже существует, его содержимое при открытии остается на месте; в противном случае создается новый файл; и в любом случае файл открывается для чтения/записи в двоичном режиме. ссжаств[4] = сап!асс.раск("лье Вакег".есссса("ьтгб"), 752) сап!асса[5] = ссп!ас!.раск!"сзпсу Осча".ессссе!"стг8"), 987) Мы можем воспринимать файл как список, и использовать оператор доступа к элементам ([]).
Здесь выполняется присваивание двух бай- 378 Глава 7. Работа с файлами товых строк (объектов Ьутев, каждый из которых содержит строку и целое число) двум записям, с использованием номеров их позиций в файле. Этн операции присваивания перезапишут прежнее содержимое, а если файл содержит менее шести записей, будут созданы новые записи, каждая из которых будет заполнена байтами Ох00. соптаст бата = сашаст.опрасн(соптаств[5]) соптаст бата[0].бесобе("отта"),гвтг(р(спг(0)) в вернет: 'с1пбу Оо»е' Поскольку строка «С[пбу Поче» содержит менее 15 символов Т)ТУ-8, при упаковывании в конец ее будут добавлены байты ОхОО.
Поэтому при извлечении записи соптаст бата будет содержать кортеж из двух элементов (Ь'С1пбу ОочетхООттхООттхООтхООтх00', 987). Чтобы получить имя, необходимо декодировать последовательность байтов в кодировке Т)Тт -8 для получения строки Юникода и потом удалить завершающие байты Ох00. Теперь, когда мы мельком увидели класс в действии, можно приступать к рассмотрению программного кода.
Определение класса В[пагуРесогбЕ11е. Вьпагулесогбр[1е находится в файле Втапуйесопг(Рйеру. Вслед за обычными предварительными сведениями следуют два частных определения значений байтов: ОЕ(ЕТЕО = Ь"1х01" ОКАТ = Ь"ггх02" Каждая запись начинается с байта «состояния», который может иметь одно из двух значений: ОЕЕЕТЕО или ОКАТ (или Ь" т,х00" в случае пустой записи). Ниже приводятся строка с инструкцией с1авв и программный код метода инициализации: с1авв Втпагупесогбг(1е: бет тп(т (ве1Г, Гт1епаее, гесогб в1ге, аыо Г1овП=Тгое); ве1Г.
гесогб в1ве = гесогб вые» 1 зобе = "н»ь" (г пот ов.рата.ехтвтв(г11епаае) е1ве "г»ь" ве!Г. ГЬ = орел(тт1епаае, аобе) ве1(.авто Г1ово = алло Г1ово Существует два разных размера записи. Значение Втпагулесогбрт1е. гесогб 812е определяется пользователем н является размером записи с точки зрения пользователя. Частное значение Втпагуйесогбр[]е.
гесогб 812е — это истинный размер записи, который включает байт состояния. Мы предотвращаем усечение файла при открытии, если файл существует (используя режим "г»Ь"), и создаем его, если файл отсутствует (используя режим Гя»Ь"). Элемент «+» в строке режима указывает, что файл открывается на чтение и запись. Если атрибут 81пагуйесогбр!- 1е.авто (1овЬ имеет значение Тгое, файл будет выталкиваться на диск перед каждой операцией чтения и после каждой операции записи. Произвольный доступ к двоичным данным з файлах 379 Зргррегту ае( гесрга а!зе(ае1(): гетогп ае1(, гесрга а(зе — 1 Фргорегту лет папе(ае1(): ге(ого ае1(.
тп.папе Се( (1оал(ае1(); ае1(. (П.Г!оал() Сет с1рае(ае1().' ае1п тл.с1сае() Мы оформили размер записи и имя файла как свойства, доступньн только для чтения. Размер записи, который сообщается пользователю, является тем размером, который был установлен пользователем при создании объекта и соответствует размеру записи пользователя.
Методы Поев() и с1оае() просто вызывают соответствующие методы объекта файла. ает ае(1теэ (ае1(, тазах, гасрга): аааегт (юпатапсе(гесргс, (путеа, оутеаггау)), Пнпагу Сага гаро(геа" аааегт 1еп(георга) == ае1(.гесагп аые, ( "гесрга воат ое ехаст1у (0) Оутаа".(ргэат( ае1(.георга аые)) ае1(. (п.апек(!паек * ае1(.
гесогз аые) ае1(. (л.нюте( ОКАу) ае)т. (п,нгые(гессга) 1( ае)даоса т)оаа: ае1(. (П, (1оаь() Этот метод обеспечивает поддержку синтаксиса агу[1] = сага, Ьгг — это объект класса В(пагуйесогбр11е, з — номер позиции записи и с(ага — строка байтов. Обратите внимание, что запись должна иметь тот же размер, что был указан при создании объекта В1пагуаесогЗР(1е. Если аргументы содержат корректные значения, выполняется перемещение указателя в файле в позицию первого байта записи — обратите внимание на то, что здесь используется истинный размер записи, то есть размер с учетом байта состояния. По умолчанию метод аеек( ) перемещает указатель в файле в абсолютную позицию.
С помощью второго аргумента можно выполнять перемещение относительно текущей позиции или относительно конца файла. (Атрибуты и методы объектов файлов перечислены в табл. 7.4.) Так как производится изменение элемента, вполне очевидно, что он не был удален, поэтому в байт состояния записывается значение ОКАУ, а затем записываются двоичные данные пользователя.
Объект ВтпагуВесогаг11е ничего не знает о структуре используемой записи, он беспокоится лишь о том, чтобы записи имели корректный размер. Глава 7. Работа с файлами Се( де(1(ев (ве1(, 1поех): ве1С вееК (о 1поех(тпсех) агате = ве1(. (п. геас(1) тт агате != ОКАТ: гетсгп испе гетсгп ве1(.
(п.геас(ве1П гесого в1ге) Таблица 7.4. Методы и атрибуты объекта файла Описание Синтаксис Г.с1ове() Закрывает объект файла Г н записывает в атрибут (, с1овео значение Тгсе Возвращает Тгсе, если файл закрыт Г.с1свео Г.епсос1пд Кодировка, используемая при преобразованиях Ьутев ++ мг Возвращает дескриптор файла. (Доступно только для объектов файлов, имеющих дескрипторы.) т.тт1епо() Выталкивает выходные буферы объекта Г на диск Г. (1свп() С т за(ту() Возвращает Тгсе, если объект файла ассоциирован сконсолью. (Доступно только для объектов файлов, ссылающихся на фактические файлы.) Режим, в котором был открыт объект файла Г Имя файла (если таковое имеется) и восе Т.паве С пеи1тпев Виды последовательностей перевода строки, встречаю- щиеся в текстовом файле Г Возвращает следующую строку из объекта файла П В большинстве случаев этот метод вызывается неявно, например, тог 11ле тп Г г пехт () Возвращает л байтов без перемещения позиции указа- теля в файле П рееК(л) Читает до соиле байтов нз объекта файла С Если значение сопле не определено, то читаются все байты, начиная от текущей позиции и до конца.
При чтении в двоичном режиме возвращает объект Ьутев, при чтении в текстовом режиме — объект вт г. Если из ничего не бы. ло прочитано (конец файла), возвращается пустой объект ьутев нлн в( г г.геас(сапог) Метод не проверяет выход индекса за допустимые границы. Если нндеке находится за пределами файла, запись будет записана в корректное местоположение, а каждый байт между прежним концом файла и началом новой записи автоматически будет установлен в значение Ь'|КОО". Такие пустые записи не имеют значения ОКАЯ или ОЕЬЕТЕО в байте состояния, благодаря этому мы сможем их отличать, когда в этом появится необходимость.
Произвольный доступ к двоичным данным в файлах 381 Синтаксис Г.геабзЬ1е() с гезбтлта(ьз) С геаб1!пе(собст) и гезб1шез(ззгелзлг) С зеех(оттает, збслСЕ) С зеекзс)е() С теп() Г.тгслса1е(юге) С ггггтзв)е() Г.ныге(з) Т ныте1шез(зеб) Описание Возвращает Тгбе, если Г был открыт для чтения Читает до 1ел(Ьа) байтов в объект Ьа типа Ьутеаггау и возвращает число прочитанных байтов (О, если был достигнут конец файла). (Доступен только в двоичном режиме.) Читает следующую строку (до собст байтов, если значе. ние собст было определено и число прочитанных байтов было достигнуто раньше, чем встретился символ перевода строки Кл), включая символ перевода строки Кл Читает все строки до конца файла и возвращает их в виде списка. Если значение аргумента збгею лт определено, то будет прочитано примерно щгелглт байтов, если внутренние механизмы, на которые опирается объект файла, поддерживают такую возможность Перемещает позицию указателя в файле (откуда будет начато выполнение следующей операции чтения или записи) в заданное смещение, если аргумент нлепсе не определен или имеет значение аз.