ФорумПрограммирование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', 'user1@mail.com', 786214569851],
    	[2, 'user2', 'user2@mail.com', 786214569852],
    	[3, 'user3', 'user3@mail.com', 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ι унц-унц

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