在Unicode识别的Delphi版本

时间:2016-02-04 10:36:47

标签: delphi delphi-xe7

我正在运行一个基于Delphi2007构建的遗留应用程序,我们通过在DB中存储字符的2byte Hex代码来处理非英语字符。 在读取时,我们应用char()将这些Hex代码转换为String。

字符串到十六进制(保存到DB之前):

strHex := Format( '%x', [ Byte( strText[ lIndex ] ) shr 4 ] );
DataStr[ lPos ] := strHex[ 1 ];
inc( lPos );

strHex := Format( '%x', [ Byte( strText[ lIndex ] ) and $0F ] );
DataStr[ lPos ] := strHex[ 1 ];
inc( lPos );

//in simple I am saving the Hex code to pcData

Hex to String(从DB读取后):

strText := strText + Chr( StrToInt('$'+ DataStr[lPos] + DataStr[lPos + 1]))

此代码在移至Delphi XE7后开始破解,其中 string 被视为UniCode String,我们显式必须将字符串转换为AnsiString类型。

将下面的字符串转换为十六进制
ТуцЕфылАшдеук8311
在Delphi 2007中给出:
  的 \ D2 \ F3 \ F6 \ C5 \ F4 \ FB \ EB \ C0 \ F8 \ E4 \ E5 \ F3 \ EA8311
在Delphi XE7中给出:
  的 \ 22 \ 43 \ 46 \ 1A \ 33 \ 4B \ 4B \ 48 \ 44 \ 42 \ 14 \ 44 \ 49 \ 33 \ 351522


我想知道修改此代码的最佳方法,以便我可以处理遗留数据。

2 个答案:

答案 0 :(得分:2)

首先,生成十六进制字符串的简单方法是使用RTL自己的BinToHex()函数,而不是编写自己的转换代码,例如:

var
  ...
  s: AnsiString;
  DataStr: string; 
  lPos: Integer;
  ...
begin
  ...
  s := '...';
  BinToHex(PAnsiChar(s), @DataStr[lPos], Length(s)); 
  Inc(lPos, Length(s)*2);
  ...
end;

然后,您可以使用HexToBin()来反转它。而且由于您正在处理编码的ANSI数据,您可以声明一个AnsiString变量,该变量与所需的代码页编码具有亲缘关系(在您的情况下,可能是1251),将十六进制代码直接读入该变量,然后分配/将其转换为正常String并让RTL为您处理转换为Unicode:

type
  Win1251String = type AnsiString(1251);
var
  ...
  tmp: Win1251String;
  DataStr, strText: string;
  lPos: Integer;
  ...
begin
  ...
  SetLength(tmp, LengthOfHex div 2);
  HexToBin(@DataStr[lPos], PAnsiChar(tmp), Length(tmp));
  strText := String(tmp);
  ...
end;

答案 1 :(得分:1)

根据评论,您只需将此数据解码为原生Unicode string即可。这样做:

  1. 将数据库中的编码文本读入string变量。
  2. 将文本解码为字节数组而不是字符串。您的Delphi 2007代码可以像它一样使用,但它需要写入字节数组而不是字符串。
  3. 该字节数组是ANSI 1251编码的。使用TEncoding.GetString对其进行解码。您需要使用正确的代码页TEncoding创建Encoding := TEncoding.GetEncoding(1251)类的实例。