1

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

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 (黄色!)?

4

1 回答 1

0

好吧,安德鲁,我似乎回答了你的很多问题。 此链接说明:

所以人们不得不想出一个奇怪的约定,在每个 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 会理解这一点。只要您只使用两个字节,移动前六个十六进制数字只会巧合地起作用。

于 2013-06-17T21:17:50.243 回答