将大的4字节整数表示为无符号二进制形式

5

我有一些整数,它们的浮点值介于4000000000-4294967000之间(这比4字节无符号整数的最大值要小)

我想将其保存到文件中,并重新读取该值。

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

在文件中,值必须是精确的4字节无符号整数,因为外部设备将期望数据格式为此。但是PHP将大值存储为浮点数,并破坏了二进制表示。

我如何以该格式将数字写入文件中?

[编辑] @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个回答

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/zh/language.operators.bitwise.php


1
把那个4字节的数字分成两个2字节的数字(整数除以256*256得到第一个字,从原始值中减去该值得到第二个字),然后分别写入两个数据包。

嘿,谢了 :) 你能检查一下我的实现是否正确运行吗? - canni

1

不用担心它是浮点数。如果它在2^31和2^32-1之间,你就不会有任何问题。

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

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

$ 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"
}

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接