首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

T-SQL base64_encode函数支持中文编码

2012-05-21 
求助T-SQL base64_encode函数支持中文编码项目实施中需要用T-SQL写一个触发器,向另一个应用系统的SQL Serv

求助T-SQL base64_encode函数支持中文编码
项目实施中需要用T-SQL写一个触发器,向另一个应用系统的SQL Server 数据库中直接写入记录,但是此应用系统的字段值是以Base64编码的,在网络中搜索到一些T-SQL Base64 EnCode函数,测试发现单字节的英文和数字编码后可以被应用系统正确解码,双字节的中文编码后,应用系统解码后是乱码。因为对SQLServer中文处理原理不是很熟悉,请高手帮助修改一下base64_encode函数,附原函数和SQLServer中文处理的一些资料。很急,谢谢!

CREATE FUNCTION base64_encode  
  (  
  @plain_text varchar(6000)  
  )  
  RETURNS  
  varchar(8000)  
  AS BEGIN  
  --local variables  
  DECLARE  
  @output varchar(8000),  
  @input_length integer,  
  @block_start integer,  
  @partial_block_start integer, -- position of last 0, 1 or 2 characters  
  @partial_block_length integer,  
  @block_val integer,  
  @map char(64)  
  SET @map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'  
  --initialise variables  
  SET @output = ''  
  --set length and count  
  SET @input_length = LEN( @plain_text + '#' ) - 1  
  SET @partial_block_length = @input_length % 3  
  SET @partial_block_start = @input_length - @partial_block_length  
  SET @block_start = 1  
  --for each block  
  WHILE @block_start < @partial_block_start BEGIN  
  SET @block_val = CAST(SUBSTRING(@plain_text, @block_start, 3) AS BINARY(3))  
  --encode the 3 character block and add to the output  
  SET @output = @output + SUBSTRING(@map, @block_val / 262144 + 1, 1)  
  + SUBSTRING(@map, (@block_val / 4096 & 63) + 1, 1)  
  + SUBSTRING(@map, (@block_val / 64 & 63 ) + 1, 1)  
  + SUBSTRING(@map, (@block_val & 63) + 1, 1)  
  --increment the counter  
  SET @block_start = @block_start + 3  
  END  
  IF @partial_block_length > 0  
  BEGIN  
  SET @block_val = CAST(SUBSTRING(@plain_text, @block_start, @partial_block_length)  
  + REPLICATE(CHAR(0), 3 - @partial_block_length) AS BINARY(3))  
  SET @output = @output  
  + SUBSTRING(@map, @block_val / 262144 + 1, 1)  
  + SUBSTRING(@map, (@block_val / 4096 & 63) + 1, 1)  
  + CASE WHEN @partial_block_length < 2  
  THEN REPLACE(SUBSTRING(@map, (@block_val / 64 & 63 ) + 1, 1), 'A', '=')  
  ELSE SUBSTRING(@map, (@block_val / 64 & 63 ) + 1, 1) END  
  + CASE WHEN @partial_block_length < 3  
  THEN REPLACE(SUBSTRING(@map, (@block_val & 63) + 1, 1), 'A', '=')  
  ELSE SUBSTRING(@map, (@block_val & 63) + 1, 1) END  


  END  
  --return the result  
  RETURN @output  
  END  
  GO

[解决办法]
关注^^^^
[解决办法]
参考该帖3楼。
[解决办法]
需要明确一点:BASE64的编码/解码,是把字节流(而不是字符串)与BASE64格式的字符串之间相互转换。

对于存放在varchar中的英文字母和数字(即ASCII字符),在多数常用字符编码(utf8,gbk,latin1)下与字节流是等价的。所以LZ的函数在这种情况下是正常的。

应用系统解码后是乱码
要看应用系统解码后使用的是什么字符编码。如果是gbk,则在数据库排序规则是"Chinese_PRC_CI_AS"的情况下应该正常。如果是utf8,参考2楼帖子中的UCS2与UTF8的互转函数。

[解决办法]

探讨
需要明确一点:BASE64的编码/解码,是把字节流(而不是字符串)与BASE64格式的字符串之间相互转换。

对于存放在varchar中的英文字母和数字(即ASCII字符),在多数常用字符编码(utf8,gbk,latin1)下与字节流是等价的。所以LZ的函数在这种情况下是正常的。

应用系统解码后是乱码
要看应用系统解码后使用的是什么字符编码。如果是gbk,则在数据库排序规则是"Chi……

[解决办法]
另:我试了一个绿色小软件,可以将BASE64的原码进行转换,发现我将编码方式选择成UTF-8时,编码与我的目标是一致的。软件作者的下载页面:http://www.cpp521.cn/post/base64.html。
请问:将编码方式选择成UTF-8进行编码,是选将原码转换成UTF-8字符串,再对UTF-8字符串进行base64编码吗?还是正好相反?
我试过这个ucs2_to_utf8函数,无论是先转UTF-8再enocode,还是后转UTF-8再enocode,都不能得到正确的目标编码。
CREATE FUNCTION dbo.ucs2_to_utf8(
@ucs2 varbinary(max)
)
RETURNS varbinary(max)
AS
/*
U-00000000 ... U-0000007F 0xxxxxxx 
U-00000080 ... U-000007FF 110xxxxx 10xxxxxx 
U-00000800 ... U-0000FFFF 1110xxxx 10xxxxxx 10xxxxxx 
*/
BEGIN
DECLARE
@output varbinary(max),
@i int,
@code int
SET @output = 0x
SET @i = 1
WHILE 1 = 1
BEGIN
SET @code = CAST(SUBSTRING(@ucs2,@i+1,1) + SUBSTRING(@ucs2,@i,1) AS int)
IF @code = 0
BREAK
IF @code >= 0x0800
SET @output = @output +
CAST(@code / 4096 + 224 AS binary(1)) +
CAST((@code % 4096) / 64 + 128 AS binary(1)) +
CAST((@code % 4096) % 64 + 128 AS binary(1))
ELSE IF @code >= 0x0080
SET @output = @output +
CAST(@code / 64 + 192 AS binary(1)) +
CAST(@code % 64 + 128 AS binary(1))
ELSE
SET @output = @output + CAST(@code AS binary(1))
SET @i = @i + 2
END
RETURN @output
END

热点排行
Bad Request.