ФорумПрограммированиеPHP для идиотов → Запись бинарных файлов

Запись бинарных файлов

  • at0m1x

    Сообщения: 10 Репутация: N Группа: Кто попало

    Spritz Март 3, 2014, 12:44 п.п.

    Как правильно записывать и считывать бинарные файлы на PHP?
    Ниже код, который выдает такую ошибку:


    Warning: unpack(): Type I: not enough input, need 4, have 1


    Т.е. не срабатывает ф-я feof. Хотя достигнув конца файла она должна остановить цикл. Возможно, при записи бинарного файла нужно самому записывать и символ EOF?


    //id,login,email,phone
    $users = [
    [1, 'user1', '[email protected]', 786214569851],
    [2, 'user2', '[email protected]', 786214569852],
    [3, 'user3', '[email protected]', 786214569853],
    ];

    $bin = '';
    foreach ($users as $values) {
    list($id, $login, $email, $phone) = $values;
    $loginLength = strlen($login);
    $emailLength = strlen($email);

    $bin .= pack("I2a{$loginLength}Ia{$emailLength}I", $id, $loginLength, $login, $emailLength, $email, $phone);
    }

    $handle = fopen('users.bin', 'wb');
    fwrite($handle, $bin);
    fclose($handle);

    //———————

    $users = [];
    $handle = fopen('users.bin', 'rb');
    while(!feof($handle)) {
    $data = fread($handle, 4);
    $data = unpack('Iid', $data);
    $result['id'] = $data['id'];

    $data = fread($handle, 4);
    $data = unpack('Ilength', $data);
    $loginLength = $data['length'];

    $data = fread($handle, $loginLength);
    $data = unpack('a*login', $data);
    $result['login'] = $data['login'];

    $data = fread($handle, 4);
    $data = unpack('Ilength', $data);
    $emailLength = $data['length'];

    $data = fread($handle, $emailLength);
    $data = unpack('a*email', $data);
    $result['email'] = $data['email'];

    $data = fread($handle, 4);
    $data = unpack('Iphone', $data);
    $result['phone'] = $phone;

    $users[] = $result;
    }
    fclose($handle);

    print_r($users);
    die;
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz Март 4, 2014, 6:48 д.п., спустя 18 часов 3 минуты 35 секунд

    Не надо записывать EOF. Функция должна срабатывать, наверное ты неправильно понимаешь результаты. Включи вывод ошибок и добавь дебажный вывод внутри цикла.

    Спустя 133 сек.

    какие-то unpack у тебя странные!
    ιιlllιlllι унц-унц
  • at0m1x

    Сообщения: 10 Репутация: N Группа: Кто попало

    Spritz Март 4, 2014, 8:10 д.п., спустя 1 час 22 минуты 37 секунд

    Сделал другим способом, заменил:


    while(!feof($handle)) {



    на


    $size = filesize ('users.bin');
    while(ftell($handle) < $size) {



    Работает отлично. Спасибо!
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz Март 4, 2014, 1:08 п.п., спустя 4 часа 57 минут 19 секунд

    feof() сигналит конец файла после того, как fread() попытается прочитать за концом файла.
    вот такое, например, будет работать:

    $users = [];
    $handle = fopen('users.bin', 'rb');
    $data = fread($handle, 4);
    while(feof($handle)) {
    // $data = fread($handle, 4); // moved to the end
    $data = unpack('Iid', $data);
    $result['id'] = $data['id'];
    … …
    $users[] = $result;

    $data = fread($handle, 4);
    }
    fclose($handle);


    Спустя 119 сек.

    в доках есть про это, правда там пишут про текстовый файл, но на саммом деле верно и для бинарных
    http://ru2.php.net/feof
    The problem when processing plain text files is that feof() will not return true after getting the last line of input. You need to try to get input _and fail_ before feof() returns true.
    ιιlllιlllι унц-унц

Пожалуйста, авторизуйтесь, чтобы написать комментарий!