将大4字节整数写为无符号二进制

时间:2010-08-31 09:33:28

标签: php serialization binary-data

我有值在值之间浮动的整数:4000000000-4294967000(小于4字节无符号整数的int max)

我希望将其保存到文件,然后重新读取值

$f = fopen($fileName, 'wb'); fwrite($f, pack('I', $value));

重要的是,在文件中,值必须是精确的4字节无符号整数,因为外部设备会期望数据格式。但PHP将大值存储为float,并销毁二进制表示。

我如何将这些数字写成该格式的文件?

[编辑] @FractalizeR这是我的工作:

protected static function handleUint($direction, $value)
{
    if($direction == 'encode')
    {
        $first2bytes    = intval($value / (256 * 256));
        $second2bytes   = intval($value - $first2bytes);

        return pack('n2', $first2bytes, $second2bytes);
    }
    else
    {
        $arr = unpack('n2ints', $value);
        $value = $arr['ints1'] * (256 * 256) + intval($arr['ints2']) - 1;
        return $value;
    }
}

但是我不太明白,为什么我必须对返回值进行-1,并且这个二进制文件是否会生成正确的?

4 个答案:

答案 0 :(得分:1)

好吧,将4个字节的数字分成2个2字节的数字(整数除以256 * 256得到第一个字,然后从原来的一个字减去该值得到第二个字)并写入两个包。

答案 1 :(得分:1)

如果要将int分成4个字节,可以执行以下操作:

int x = 13434;
byte[] buff = new byte[] {
       (byte)((x >> 24) & 0xff),
       (byte)((x >> 16) & 0xff),
       (byte)((x >> 8) & 0xff),
       (byte((x) & 0xff)
}

此处使用的方法称为按位运算。

请参阅:http://en.wikipedia.org/wiki/Bitwise_operation

希望这会有所帮助。

修改

我认为这就是你在PHP中做同样的事情:

$arr = array(
       ((x >> 24) & 0xff),
       ((x >> 16) & 0xff),
       ((x >> 8) & 0xff),
       (x & 0xff)
);

请参阅:http://php.net/manual/en/language.operators.bitwise.php

答案 2 :(得分:1)

不要担心它是漂浮物。如果它在2 ^ 31和2 ^ 32-1之间,你将不会有任何问题。

PHP浮点数具有52位尾数,因此可以存储而不会丢失32位数字的精度。

你告诉pack编码一个整数,你传递一个浮点数,它会将浮点数转换为整数。浮点值为2 ^ 31和2 ^ 32-1之间的整数,在32位计算机上转换为负数:

$ php -r "var_dump((int) 4000000000);"
int(-294967296)

在64位计算机上,您也得到一个整数:

$ php -r "var_dump((int) 4000000000);"
int(4000000000)

但他们的字节表示完全相同。 pack将在两者上返回相同内容:

$ php -r "var_dump(unpack('H*', pack('I', (float) 4000000000)));"
array(1) {
  [1]=>
  string(8) "00286bee"
}

答案 3 :(得分:-1)

使用bcmath()处理您的号码,并进行保存,请按照FractalizeR的说法进行操作。

一般情况下,请参阅Arithmetic with Arbitrarily Large Integers in PHP