用于signed 32 int - big endian的PHP pack()格式

时间:2013-04-16 14:28:20

标签: php pack

我正在使用PHP,fopen,fseek,pack等创建然后将数据写入文件(一个新的'ESRI Shape文件')。文件规范在这里http://www.esri.com/library/whitepapers/pdfs/shapefile.pdf

文件规范声明所写的数据必须是以下各项的组合:

  • 整数:有符号32位整数(4字节) - Big Endian
  • 整数:有符号32位整数(4字节) - Little Endian
  • Double:有符号64位IEEE双精度浮点数(8字节) - Little Endian

我似乎无法找到允许这些格式的pack()格式。我不想使用依赖于机器的格式,因为此代码可能在各种平台上运行。

有人可以就这3种格式需要使用的格式(或格式组合)提出建议吗?

非常感谢, 史蒂夫

2 个答案:

答案 0 :(得分:5)

如果PHP不支持它,您可以实现自己的。

function pack_int32be($i) {
   if ($i < -2147483648 || $i > 2147483647) {
      die("Out of bounds");
   }
   return pack('C4',
      ($i >> 24) & 0xFF,
      ($i >> 16) & 0xFF,
      ($i >>  8) & 0xFF,
      ($i >>  0) & 0xFF
   );
}

function pack_int32le($i) {
   if ($i < -2147483648 || $i > 2147483647) {
      die("Out of bounds");
   }
   return pack('C4',
      ($i >>  0) & 0xFF,
      ($i >>  8) & 0xFF,
      ($i >> 16) & 0xFF,
      ($i >> 24) & 0xFF
   );
}

双精度LE要困难得多。支持四精度系统将涉及使用d打包数字,将其转换为二进制字符串,将二进制文件拆分为字段,如果字段太大则将字段截断为正确的大小,连接字段,然后转换从二进制到字节。

答案 1 :(得分:3)

您可以检查运行代码的计算机的字节顺序,并根据需要手动反转字节。下面的代码应该可以工作,但是你一次只能转换一个int或者浮点数。

define('BIG_ENDIAN', pack('L', 1) === pack('N', 1));

function pack_int32s_be($n) {
    if (BIG_ENDIAN) {
        return pack('l', $n); // that's a lower case L
    }
    return strrev(pack('l', $n));
}
function pack_int32s_le($n) {
    if (BIG_ENDIAN) {
        return strrev(pack('l', $n));
    }
    return pack('l', $n); // that's a lower case L
}
function pack_double_be($n) {
    if (BIG_ENDIAN) {
        return pack('d', $n);
    }
    return strrev(pack('d', $n));
}
function pack_double_le($n) {
    if (BIG_ENDIAN) {
        return strrev(pack('d', $n));
    }
    return pack('d', $n);
}