3

我正在使用 PHP、fopen、fseek、pack 等创建并将数据写入文件(新的“ESRI 形状文件”)。文件规范在这里http://www.esri.com/library/whitepapers/pdfs/形状文件.pdf

文件规范指出,写入的数据需要结合以下内容:

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

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

谁能建议我需要为这 3 种格式使用什么格式(或格式组合)?

非常感谢,史蒂夫

4

2 回答 2

6

您可以检查运行代码的机器的字节顺序,并根据需要手动反转字节。下面的代码应该可以工作,但您一次只能转换一个 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);
}
于 2013-04-16T15:20:00.200 回答
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,将其转换为二进制字符串,将二进制拆分为字段,如果字段太大,则将字段截断为正确的大小,连接字段,然后从二进制转换为字节。

于 2013-04-16T15:40:07.180 回答