Анимация
JavaScript
|
Главная Библионтека 8.14. Чтение строки из двоичного файла З!"! > Смотри также- Описание функций open, seek, read, pack и unpack вperlfunc(i); рецепты 8.12; 8.14. 8.14. Чтение строки из двоичного файла Проблема Требуется прочитать из файла строку, завершенную нуль-символом, начиная с определенного адреса. Решение Присвойте $/ нуль-символ ASCII и прочитайте строку с помощью <>: $old rs = $/, # Сохранить старое значение $/ $/ = \0 # Нуль-символ seek(FH, $addr, SEEK SET) or die Seek error $\n Sstring = <FH> # Прочитать строку chomp Sstring, » Удалить нуль-символ $/ = $old rs, # Восстановить старое значение $/ При желании сохранение и восстановление $/ можно реализовать с помощью local: local $/ = \0 # } й $/ восстанавливается автоматически Комментарий Программа bgets из примера 8.5 получает в качестве аргументов имя файла и одно или несколько байтовых смещений. Допускается десятичная, восьмеричная или шестнадцатеричная запись смещений. Для каждого смещения программа читает и выводит строку, которая начинается в данной позиции и завершается нуль-символом или концом файла: Пример 8.5. bgets #1/usr/bin/perl й bgets - вывод строк по смещениям в двоичном файле use 10 Seekable, (Sfile, @addrs) = @ARGV or die usage SO addr open(FH Sfile) or die cannot open Sfile $i , S/ = \000 , foreach $addr (@addrs) { Saddr = oct Saddr if $addr =~ /"0/, seek(FH, Saddr, SEEK SET) 312 Глава 8 • Содержимое файлов Пример 8.5 (продолжение) or die can t seek to $addr in $file $ , printf qq{%#x %#o %d %s \n} $addr, $addr, $addr scalar <> > Приведем простейшую реализацию программы UNIX strings-Пример 8.6. strings #1 /usr/bm/perl n strings - извлечение строк из двоичного файла $/ = \0 while (О) { while (/([\040-\176\s]{4 })/g) { print $1, \n \> Смотри также- Описание функций seek, get с и ord в perlfunc(l); описание qq в разделе « Quote and Quote-like Operators» шап-страницы per/op( 1) 8.15. Чтение записей фиксированной длины Проблема Требуется прочитать файл с записями фиксированной длины Решение Воспользуйтесь функциями раек и unpack: # SRECORDSIZE - длина записи в байтах # STEMPLATE - шаблон распаковки для записи » FILE - файл из которого читаются данные # (giFIELDS - массив для хранения полей until ( eof(FILE) ) { read{FILE Srecord SRECORDSIZE) == $RECORDSIZE or die short read\n (SFIELDS = unpack($TEMPLATE Srecord), Комментарий Поскольку мы работаем не с текстовым, а с двоичным файлом, для чтения записей нельзя воспользоваться оператором < > или методом getline модулей 10 Вместо этого приходится считывать конкретное количество байт в буфер 8.15. Чтение записей фиксированной длины 313 функцией read. После этого буфер содержит данные одной записи, которые декодируются функцией unpack с правильным форматом. При работе с двоичными данными трудности часто начинаются как раз с правильного выбора формата. Если данные были записаны программой на С, приходится просматривать заголовочные файлы С или страницы руководства с описанием структур, для чего необходимо знание языка С. Заодно вы должны близко подружиться с компилятором С, поскольку без этого вам будет трудно разобраться с выравниванием полей (например, х2 в формате из рецепта 8 18) Если вам посчастливилось работать в Berkeley UNIX или в системе с поддержкой дсс, вы сможете воспользоваться утилитой c2ph, распространяемой с Perl, и заставить компилятор С помочь вам в этом. Программа tailwtmp в конце этой главы использует формат, описанный в иШр{5) системы Linux, и работает с файлами /var/log/wtmp и /var/run/utmp Но стоит вам привыкнуть к работе с двоичными данными, как возникает другая напасть - особенности конкретных компьютеров Вероятно, программа не будет работать в вашей системе без изменений, но выглядит она поучительно. Приведем соответ-ствуюшую структуру из заголовочного файла С для Linux: Wdefine UT LINESIZE 12 ftdefine UT NAMESIZE 8 #define UT HOSTSIZE 16
Вычисленная двоичная структура (в нашем примере - s х2 i А12 А2 х2 1 А8 А16 1 ) передается раек с пустым списком полей для определения размера записи. Не забудьте проверить код возврата read при чтении записи, чтобы убедиться в том, что вы получили запрошенное количество байт. Если записи представляют собой текстовые строки, используйте шаблон распаковки а или А . Записи фиксированной длины хороши тем, что п-я запись начинается в файле со смещения SIZE*(n-1), где SIZE - размер одной записи. Пример приведен в программе с построением индекса из рецепта 8.8. [> Смотри также- Описание функций unpack, pack и read вperlfunc(l), рецепт 1.1. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 [ 98 ] 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |