带签名的32 int的PHP pack()格式-Big Endian

use*_*262 3 php pack

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

文件规范指出,写入的数据必须是以下各项的组合:

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

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

谁能建议我这三种格式需要使用哪种格式(或格式组合)?

非常感谢,史蒂夫

mcr*_*ley 5

您可以检查运行代码的机器的字节序,并根据需要手动反转字节。下面的代码应该可以工作,但一次只能转换一个 int 或 float。

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);
}
Run Code Online (Sandbox Code Playgroud)


ike*_*ami 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
   );
}
Run Code Online (Sandbox Code Playgroud)

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