汉字的base64编码
base64 encode for chinese chars
我正在使用以下两种方法以 base 64 编码中文字符串。问题是我有 Pz8=
作为输出,解码后是 ??
这有什么问题,我该如何解决?
方法一
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]('你好')
方法二
SELECT CAST('你好' as varbinary(max)) FOR XML PATH(''), BINARY BASE64
您缺少 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-8
、UTF-16
、ASCII
等不同……更糟糕的是还有 BE 和 LE。
获得base64
的步骤是:
- 获取我的值的位模式(一个字符串,一个日期,一张图片,实际上任何值)
- 计算此位模式的
base64
重新编码的步骤是
- 计算在
base64
中隐藏的原始位模式
- 将位模式解释为原始值
最后一步可能会引起混淆...您必须确切知道系统使用哪种二进制表示。您必须使用 完全 相同的数据类型和 完全 相同的解释才能取回值。
对于字符串,人们必须知道,SQL-Server 本身的选择非常有限。
- 有
NVARCHAR
(NCHAR
),是2字节编码的unicode UCS-2
flavor(几乎和utf-16
)
- 还有
VARCHAR
(CHAR
),是1字节编码的扩展ASCII。所有 非拉丁语 字符都绑定到连接排序规则中的代码页。但是这不是UTF-8!
我正在使用以下两种方法以 base 64 编码中文字符串。问题是我有 Pz8=
作为输出,解码后是 ??
这有什么问题,我该如何解决?
方法一
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]('你好')
方法二
SELECT CAST('你好' as varbinary(max)) FOR XML PATH(''), BINARY BASE64
您缺少 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-8
、UTF-16
、ASCII
等不同……更糟糕的是还有 BE 和 LE。
获得base64
的步骤是:
- 获取我的值的位模式(一个字符串,一个日期,一张图片,实际上任何值)
- 计算此位模式的
base64
重新编码的步骤是
- 计算在
base64
中隐藏的原始位模式
- 将位模式解释为原始值
最后一步可能会引起混淆...您必须确切知道系统使用哪种二进制表示。您必须使用 完全 相同的数据类型和 完全 相同的解释才能取回值。
对于字符串,人们必须知道,SQL-Server 本身的选择非常有限。
- 有
NVARCHAR
(NCHAR
),是2字节编码的unicodeUCS-2
flavor(几乎和utf-16
) - 还有
VARCHAR
(CHAR
),是1字节编码的扩展ASCII。所有 非拉丁语 字符都绑定到连接排序规则中的代码页。但是这不是UTF-8!