【问题标题】:Converting to hex in php not the same as MSSQL在 php 中转换为十六进制与 MSSQL 不同
【发布时间】:2012-04-30 19:22:06
【问题描述】:

this question 的答案中,我试图通过将字符串转换为十六进制并比较这些值来使我的程序更安全,而不是直接危险地使用来自用户的字符串。我修改了该问题的代码以添加转换:

function mssql_escape($data) {
    if(is_numeric($data))
        return $data;

    $data = iconv("ISO-8859-1", "UTF-16", $data);

    $unpacked = unpack('H*hex', $data);

    return '0x' . $unpacked['hex'];
}

我这样做是因为在我的数据库中我使用的是 nvarchar 而不是 varchar。现在,当我在 php 端运行它时,它会出现

0xfeff00680065006c006c006f00200077006f0072006c00640021

然后我运行以下查询:

 declare @test nvarchar(100);
 set @test = 'hello world!';
 select CONVERT(VARBINARY(MAX), @test);

结果:

0x680065006C006C006F00200077006F0072006C0064002100

现在您会注意到这些数字几乎相同。除了尾随零之外,唯一的区别是 feff00。为什么会在那里?我意识到我所要做的就是转变,但我真的很想知道它为什么在那里,而不是仅仅做出假设。谁能向我解释为什么 php 决定在我的十六进制前面抛出 feff00(黄色!)?

【问题讨论】:

    标签: php sql-server character-encoding hex


    【解决方案1】:

    嗯,安德鲁,我似乎回答了你的很多问题。 This link 解释:

    所以人们不得不想出一个奇怪的约定 在每个 Unicode 字符串的开头存储一个 FE FF;这是 称为 Unicode 字节顺序标记,如果你正在交换你的高和 低字节它看起来像一个 FF FE 和阅读你的字符串的人 会知道他们必须每隔一个字节交换一次。呸。不是每个 野生的Unicode字符串在开头有一个字节顺序标记。

    维基百科解释说:

    如果 16 位单元以大端字节顺序表示,则此 BOM 字符将出现在字节序列中,为 0xFE,后跟 0xFF。此序列在文本中显示为 ISO-8859-1 字符 þÿ 期望文本为 ISO-8859-1 的显示。

    如果是 16 位单位 使用 little-endian 顺序,字节序列后面会有 0xFF 通过 0xFE。此序列显示为 ISO-8859-1 字符 ÿþ 期望文本为 ISO-8859-1 的文本显示。

    所以您使用 FEFF 显示的代码,这意味着它是大端表示法。对小端使用 UTF-16LE,SQL 会理解这一点。只要您只使用两个字节,移动前六个十六进制数字只会巧合地起作用。

    【讨论】:

      猜你喜欢
      • 2018-09-13
      • 1970-01-01
      • 1970-01-01
      • 2014-01-09
      • 2015-06-25
      • 2013-03-10
      • 1970-01-01
      • 2018-09-04
      • 1970-01-01
      相关资源
      最近更新 更多