二进制安全使用php写入文件以创建DBF文件

时间:2018-05-31 16:24:07

标签: php dbf

我需要使用php函数拆分一个大的DBF文件,这意味着我有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 :(得分:1)

  

据我所知,DBF文件是用2行文件构建的:   第一行包含文件信息,标题信息和二进制文件。该   第二行包含数据及其纯文本。

嗯,它有点复杂。

有关dbf文件格式的完整说明,请参阅here

因此,如果您可以使用库来读取和写入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)
  • 该文件可能以文件结尾标记0x1A结束,因此您也必须检查该文件。