从 fread() 转换为 sql 字段内容

Converting from fread() to sql field contents

我有一段代码试图从基于文件的系统移动到存储在数据库中的 blob,但是我很难找到与 fread() 方法等效的基于字符串的方法.

我尝试转换的代码如下:

$max_codewords_array=array(0,26,44,70,100,134,172,196,242,292,346,404,466,532,581,655,733,815,901,991,1085,1156, 1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465,2611,2761,2876,3034,3196,3362,3532,3706);
$max_codewords=$max_codewords_array[$this->qrcode_version];
$max_modules_1side=17+($this->qrcode_version <<2);
$matrix_remain_bit=array(0,0,7,7,7,7,7,0,0,0,0,0,0,0,3,3,3,3,3,3,3,4,4,4,4,4,4,4,3,3,3,3,3,3,3,0,0,0,0,0,0);

/* ---- read version ECC data file */
$byte_num=$matrix_remain_bit[$this->qrcode_version]+($max_codewords << 3);
$filename=QRCODE_DATA_PATH."/qrv".$this->qrcode_version."_".$ec.".dat";

$fp1 = fopen ($filename, "rb");
$matx=fread($fp1,$byte_num);
$maty=fread($fp1,$byte_num);
$masks=fread($fp1,$byte_num);
$fi_x=fread($fp1,15);
$fi_y=fread($fp1,15);
$rs_ecc_codewords=ord(fread($fp1,1));
$rso=fread($fp1,128);
fclose($fp1);

我将数据作为 bin2hex ( gzencode( str ) ) 存储在数据库中名为 'Data' 的字段中,并且可以毫无问题地将此数据读回变量,如下所示:

$data = gzdecode(hex2bin($field['Data']));

然而,当谈到 fread() 部分时,我不确定如何以二进制安全的方式交换所有这些命令。 (又名,新的 $data 值包含 fread() 通常分块通过的整个文件内容)

以下是我希望用等效的二进制安全字符串方法替换 fread() 的代码,而不是 $fp1 文件句柄,使用存储在 $data 中的内容(如上面提到过)。

$matx=fread($fp1,$byte_num);
$maty=fread($fp1,$byte_num);
$masks=fread($fp1,$byte_num);
$fi_x=fread($fp1,15);
$fi_y=fread($fp1,15);
$rs_ecc_codewords=ord(fread($fp1,1));
$rso=fread($fp1,128);

(在等待答案时,我写了这个有效的解决方案)

字符串readerclass

class sread {
    static $position = 0;
    static $data;

    public static function open($data) {
        self::$data = $data;
    }

    public static function read($bytes) {
        if( (self::$position + $bytes ) >= strlen(self::$data) ) {
            $data = substr(self::$data, self::$position);
        } else {
            $data = substr(self::$data, self::$position, $bytes);
        }
        self::$position = self::$position + strlen($data);
        return $data;
    }

    public static function close() {
        self::$data = null;
        self::$position = 0;
    }
}

用法

$data = ""; // the long string containing the data you wish to move through

sread::open($data);
$matx = sread::read($byte_num);
$maty = sread::read($byte_num);
$masks = sread::read($byte_num);
$f1_x = sread::read(15);
$f1_y = sread::read(15);
$rs_ecc_codewords = ord(sread::read(1));
$rso = sread::read(128);
sread::close();

这是一个非常粗略的示例,但您可以随意对其进行扩展。 Barmars 解决方案做同样的事情,但是这个 class 为您处理字节增量,并且几乎与 fread() 的直接替换语法相同。接受 Barmars 解决方案:)

使用 substr,并在浏览数据时使用变量跟踪当前位置。

$curpos = 0;
$matx = substr($data, $curpos, $byte_num);
$curpos += $byte_num;
$maty = substr($data, $curpos, $byte_num);
$curpos += $byte_num;
$masks = substr($data, $curpos, $byte_num);
$curpos += $byte_num;
$fi_x = substr($data, $curpos, 15);
$curpos += 15;
$fi_y = substr($data, $curpos, 15);
$curpos += 15;
$rs_ecc_codewords = ord(substr($data, $curpos, 1));
$curpos += 1;
$rso = substr($data, $curpos, 128);

另一种方法是使用正则表达式将每个部分提取为捕获组:

$regex = "/(.{$byte_num})(.{$byte_num})(.{$byte_num})(.{15})(.{15})(.)(.{128})/";
preg_match($regex, $data, $match);
list ($ignore, $matx, $maty, $masks, $fi_x, $fi_y, $rs_ecc_char, $rso) = $match;
$rss_ecc_codewords = ord($rss_ecc_char);