бинарная безопасная запись в файл с помощью php для создания файла DBF - PullRequest
0 голосов
/ 31 мая 2018

Мне нужно разделить большой файл DBF с помощью функций php, это означает, что у меня есть, например, 1000 записей, мне нужно создать 2 файла с 500 записями в каждом.

У меня нет и расширение dbase доступнони я не могу установить его, поэтому я должен работать с основными функциями PHP.Используя базовую функцию fread, я могу правильно прочитать и проанализировать файл, но когда я пытаюсь написать новый dbf, у меня возникают некоторые проблемы.

Как я понял, файл DBF структурирован в виде2-строчный файл: первая строка содержит информацию о файле, информацию заголовка и в двоичном виде.Вторая строка содержит данные и представляет собой простой текст.Поэтому я подумал просто написать новый двоичный файл, реплицирующий первую строку и вручную добавив первые записи в первый файл, остальные записи в другой файл.

Это код, который я использую для анализа файла, и онработает хорошо

    $fdbf = fopen($_FILES['userfile']['tmp_name'],'r');
    $fields = array();
    $buf = fread($fdbf,32);
    $header=unpack( "VRecordCount/vFirstRecord/vRecordLength", substr($buf,4,8));
    $goon = true;
    $unpackString='';
    while ($goon && !feof($fdbf)) { // read fields:
        $buf = fread($fdbf,32);
        if (substr($buf,0,1)==chr(13)) {$goon=false;} // end of field list
        else {
            $field=unpack( "a11fieldname/A1fieldtype/Voffset/Cfieldlen/Cfielddec", substr($buf,0,18));

            $unpackString.="A$field[fieldlen]$field[fieldname]/";
            array_push($fields, $field);
        }
    }
    fseek($fdbf, 0);
    $first_line = fread($fdbf, $header['FirstRecord']+1);

    fseek($fdbf, $header['FirstRecord']+1); // move back to the start of the first record (after the field definitions)

first_line - это переменная, содержащая данные заголовка, но когда я пытаюсь записать это в новый файл, происходит что-то неправильное, и строка не записывается точно так, как она была прочитана.Вот код, который я использую для написания:

$handle_log = fopen($new_filename, "wb");
fwrite($handle_log, $first_line, strlen($first_line) );
fwrite($handle_log, $string );
fclose($handle_log);

Я пытался добавить значение b к параметру fopen mode, как предложено, чтобы открыть его в двоичном виде, я такжепринял предложение добавить точно длину строки, чтобы избежать полос некоторых символов, но безуспешно, поскольку все записанные файлы не в правильном формате DBF.Что я могу сделать, чтобы достичь своей цели?

1 Ответ

0 голосов
/ 17 июня 2018

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

Ну, это немного сложнее, чем это.

См. здесь для полного описанияФормат файла dbf.

Так что было бы лучше, если бы вы могли использовать библиотеку для чтения и записи файлов dbf.

Если вам действительно нужно сделать это самостоятельно, вот самые важные части:

  • Dbf - это двоичный формат файла, поэтому вам нужно прочитать и записать его как двоичный файл .Например, количество записей хранится в 32-разрядном целом числе, которое может содержать ноль байтов.
  • Вы не можете использовать строковые функции для этих двоичных данных .Например, strlen() отсканирует данные до первого нулевого байта, который присутствует в этом 32-разрядном целом числе, и вернет неправильное значение.
  • Если вы разделите файл (записи), вы 'Придется отрегулировать количество записей в заголовке.
  • При разбиении записей помните, что каждой записи предшествует дополнительный байт, пробел 0x20, если запись не удалена, звездочка 0x2A если запись удалена.(например, если у вас есть 4 поля по 10 байт, длина каждой записи будет равна 41) - это значение также доступно в заголовке: bytes 10-11 - 16-bit number - Number of bytes in the record. (Least significant byte first)
  • Файл может заканчиваться концом-file маркер 0x1A, так что вам придется проверить и это.
...