Пятница, 24.11.2017, 10:27
Приветствую Вас Гость | RSS
Главная | Лекции | Регистрация | Вход
Меню сайта
Форма входа
Логин:
Пароль:
Категории раздела
Лекция [24]
Мини-чат
100
Поиск
Наш опрос
Оцените мой сайт
Всего ответов: 2
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0
    Программирование Perl
    Главная » Статьи » Лекция » Лекция

    Лекция 9.2: Средства ввода-вывода

    Ввод-вывод двоичных данных

    Двоичные данные обычно хранятся в файлах без разделителей записей в блоках фиксированной длины. После открытия двоичного файла функцией open() нужно установить режим обработки двоичных данных с помощью функции binmode().

     
    open(my $fh, ">$file") or die("Ошибка открытия: $!");
    binmode($fh);
     

    Запись двоичных данных или данных фиксированной длины может выполняться с помощью функции print($fh $record). Также имеется функция небуферизованного вывода syswrite(), которой при вызове указываются три аргумента: файловыйманипулятор, скалярная переменная с выводимыми данными и размер записываемого блока данных. Эта функция возвращает число фактически записанных байт (в случае ошибки syswrite возвращает undef ), что можно использовать для проверки успешности записи. Это делается так:

     
    syswrite($fh, $record, length($record)) == length($record)
     or die("Ошибка записи: $!");
     

    Преобразование данных к двоичному виду производит функция pack(), которая упаковывает в скалярную переменную списокзначений в соответствии с указанным шаблоном. В шаблоне каждое преобразуемое поле обозначается с помощью латинской буквы. Полный перечень шаблонов преобразования для функций pack() и unpack() приводится в таблице 9.2. За каждым символом в шаблоне может следовать десятичное число, которое рассматривается как ширина преобразуемого поля. Поля в шаблоне могут разделяться пробелами для удобства чтения.

     
    Таблица 9.2. Шаблоны упаковки и распаковки данных
    Шаблон Мнемоника Описание преобразования
    a Arbitrary произвольная последовательность байтов, дополненная нулевым байтом \0
    A ASCII строка символов ASCII, дополненная пробелами
    b / B Bit string строка битов с возрастающим / убывающим порядком битов
    c / C Character однобайтовые символы со знаком / без знака
    f / d Float / Double число с плавающей точкой одинарной / двойной точности
    F Float число с плавающей точкой одинарной точности во внутреннем представлении (NV)
    D long Double длинное число с плавающей точкой двойной точности
    h / H Hex string шестнадцатеричная строка с младшим / старшим полубайтом (nybble) в начале
    i / I Integer целое (>=32 бита) число со знаком / без знака
    j / J   целое во внутреннем представлении со знаком (IV) / без знака (UV)
    l / L Long длинное (32 бита) целое со знаком / без знака
    n / N Network беззнаковое короткое (16 битов) / длинное (32 бита) целое с сетевым порядком байтов (big endian)
    p / P Pointer указатель на строку, оканчивающуюся \0 / фиксированной длины
    q / Q Quad сверхдлинное (64 битацелое число со знаком / без знака
    s / S Short короткое (16 битов) целое со знаком / без знака
    u uuencoded строка, кодированная по алгоритму uuencode
    U Unicode строка символов Unicode
    v / V VAX беззнаковое короткое (16 битов) / длинное (32 бита) целое с VAX-порядком байтов (little endian)
    w   целое, сжатое в соответствии с кодировкой BER
    x   вставка \0 (pack) / пропуск байта по направлению вперед (unpack)
    X   пропуск байта по направлению назад
    Z ASCIIZ строка ASCIIZ (оканчивающаяся \0), дополненная \0
    @   заполнение \0 до указанной позиции
     

    Например, целочисленное значение, возвращаемое функцией time(), и дробное значение, возвращаемое функцией rand(), можно упаковать в переменную $record с помощью шаблона 'l1 d1', который означает: "одно длинное целое число (long) и одно число с плавающей точкой двойной точности (double)".

     
    $record = pack 'l1 d1', time(), rand(); #
     

    Вот еще несколько несложных примеров использования разных шаблонов для функции pack():

     
    $bin = pack('a5', 'Yes'); # в $bin будет: 'Yes\0\0'
    $bin = pack('A5', 'Yes'); # в $bin будет: 'Yes '
    $bin = pack('a4', 'abcd','x','y','z'); # в $bin: 'abcd'
    $bin = pack('aaaa', 'abcd','x','y','z'); # в $bin: 'axyz'
    $bin = pack('C2', 65,66,67); # в $bin будет: 'AB'
    $bin = pack('U2', 0x263A, 0x263B); # в $bin будет: '??'
    $bin = pack ('cxxc', 65,66); # в $bin будет: 'A\0\0B'
     

    Для преобразования данных из двоичного вида применяется функция unpack(), которая распаковывает из скалярной переменной в список или массив значения двоичных данных в соответствии с указанным шаблоном.

     
    @list_of_values = unpack($template, $binary_record);
     

    Кроме того, с помощью функции unpack() можно из строки извлекать подстроки фиксированной длины. Например, так можно извлечь из записи файла поля определенной длины в переменные:

     
    # Поля данных в записи файла:
    # c 1 по 7 байт - номер телефона
    # с 8 длиной 30 - фамилия, имя, отчество абонента
    # с 38 длиной 25 - адрес
    # 1234567Бендер Остап Ибрагимович РСФСР, Черноморск
    ($phone, $name, $address)= unpack('A7A30A25', $record);
     

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

     
    ($name, $address)= unpack('x7A30A25', $record);
     

    Подробное описание шаблонов и работы функций pack() и unpack() можно найти в стандартной документации с помощью все той же утилиты чтения документации:

     
    perldoc perlpacktut
     

    Для чтения двоичных данных или текстовых данных фиксированной длины применяется функция read(), которой в качествеаргументов передаются файловый манипулятор, скалярная переменная для вводимых данных и размер считываемого блока данных. Вот так, например, выглядит типичный цикл чтения двоичных данных:

     
    until(eof($fh)) { # читать до достижения конца файла
     # считать очередной блок данных и проверить его длину
     read($fh, $record, $record_size) == $record_size 
     or die('Неправильная длина данных');
     # распаковать данные по шаблону из $record в @data
     @data = unpack($template, $record);
     # обработать введенные данные...
    }

    Ввод-вывод с произвольным доступом

    При работе с данными фиксированной длины обычной практикой является считывание или запись данных в произвольном местефайла, например, при изменении только что считанного блока данных. Для этого нужно указать позицию чтения или записи. Это делается с помощью функции seek(), которой передается три аргумента: файловый манипулятор, смещение в байтах иуказатель позиции отсчета. Позиция отсчета задается числами: 0 - от начала файла, 1 - от текущей позиции, 2 - от конца файла. Например:

     
    seek($handle, 64, 0); # переместиться на 64 байта от начала
    seek($handle, 25, 1); # сместиться на 25 байт вперед
    seek($handle, -10, 2); # установиться на 10 байт до конца
    seek($handle, 0, 0); # установить позицию в начало файла
     

    С помощью функции tell(), которая возвращает смещение относительно начала файла, можно узнать текущую позицию чтения-записи и использовать ее для дальнейших перемещений по файлу.

     
    $pos = tell($handle); # запомнить текущую позицию в $pos
    seek($handle, $pos-5, 0); # сместиться на 5 байт назад
     

    В следующем примере увеличивается поле счетчика длиной 2 байта, расположенное в файле с позиции $new_pos:

     
    seek($file, $new_pos, 0); # установить позицию чтения
    $pos = tell($file); # и запомнить ее в переменной
    read($file, $number, 2); # прочитать 2-байтовое поле
    seek($file, $pos, 0); # установить в исходную позицию
    syswrite($file, ++$number, 2); # записать новое значение
     

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

    Категория: Лекция | Добавил: mazay (13.05.2014)
    Просмотров: 97 | Рейтинг: 0.0/0
    Всего комментариев: 0
    Добавлять комментарии могут только зарегистрированные пользователи.
    [ Регистрация | Вход ]
    Создать бесплатный сайт с uCozCopyright MyCorp © 2017