base64编码用于中文字符

时间:2018-06-04 15:23:47

标签: sql-server tsql base64 chinese-locale

我使用以下两种方法在base 64中编码一个中文字符串。问题是我输出Pz8=,解码为??

这有什么问题,我该如何解决?

方法1

CREATE FUNCTION [dbo].[base64Encode] (@input VARCHAR(MAX))
RETURNS NVARCHAR(MAX)
AS
BEGIN
    DECLARE @output NVARCHAR(MAX),
        @bits VARBINARY(3),
        @pos INT

    SET @pos = 1
    SET @output = ''

    WHILE @pos <= LEN(@input)
    BEGIN
        SET @bits = CONVERT(VARBINARY(3), SUBSTRING(@input, @pos, 3))
        SET @output = @output + SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', SUBSTRING(@bits, 1, 1) / 4 + 1, 1)
        SET @output = @output + SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', SUBSTRING(@bits, 1, 1) % 4 * 16 + SUBSTRING(@bits, 2, 1) / 16 + 1, 1)
        SET @output = @output + SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', SUBSTRING(@bits, 2, 1) % 16 * 4 + SUBSTRING(@bits, 3, 1) / 64 + 1, 1)
        SET @output = @output + SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', SUBSTRING(@bits, 3, 1) % 64 + 1, 1)
        SET @pos = @pos + 3
    END

    RETURN (LEFT(@output, LEN(@output) - 3 + LEN(@bits)) + REPLICATE('=', 3 - LEN(@bits)))
END

SELECT [dbo].[base64Encode]('你好')

方法2

SELECT CAST('你好' as varbinary(max)) FOR XML PATH(''), BINARY BASE64

1 个答案:

答案 0 :(得分:2)

您缺少N将字符串文字标记为 unicode

 SELECT N'你好' AS unicode
       ,'你好' AS ASCII

尝试这样做可以从中文字符中获得base64,反之亦然:

SELECT (SELECT CAST(N'你好' AS VARBINARY(MAX)) FOR XML PATH(''),TYPE).value(N'.','nvarchar(max)');

您得到此base64结果:YE99WQ ==

这是将base64重新转换为原始值

的方法
SELECT CAST(CAST('<x>' + 'YE99WQ==' + '</x>' AS XML).value('.','varbinary(max)') AS NVARCHAR(MAX));

更新有关重新编码的一些词语

base64不对字符串值进行编码,而是对系统用于将该字符串保留在内存中的二进制模式(实际上对任何数据类型都有效)。字符串的位模式与UTF-8UTF-16ASCII不同......更糟糕的是BE和LE。

获取base64的步骤是:

  • 获取我的值的位模式(字符串,日期,图片,实际上的任何值)
  • 计算此位模式的base64

重新编码的步骤是

  • 计算base64
  • 隐藏的原始位模式
  • 将位模式解释为原始

最后一步可能会引起混淆......你必须知道完全系统使用哪种二进制表示。您必须使用完全相同的数据类型与完全相同的解释才能获得值。

对于字符串,必须知道,SQL-Server本身的选择非常有限。

  • NVARCHARNCHAR),UCS-2风格的 2字节编码的unicode (几乎与utf-16相同)
  • 还有VARCHARCHAR),它是 1字节编码的扩展ASCII 。所有非拉丁字符都绑定到连接排序规则中的代码页。但这不是UTF-8!