如何使用EncdDec库对字符串进行编码

时间:2014-02-19 14:17:23

标签: delphi

我有这个基本代码,应该编码一个字符串,然后将其取回。但是,解码后的文本是垃圾。

procedure TForm5.Button2Click(Sender: TObject);
VAR s1, s2, s3: String;
    i: Integer;
begin
 for i:= 1 to 200
  DO s1:= s1+ char(Random(255));

 s1:= EncdDecd.EncodeString(s1);
 s3:= EncdDecd.DecodeString(s2);

 if s1= s3
 then Caption:= 'Equal'
 else Caption:= 'Not equal';
end;

更新
如果我做char(Random(128))而不是255!

2 个答案:

答案 0 :(得分:5)

问题在于Soap.EncdDecd单位:

function EncodeString(const Input: string): string;
var
  InStr, OutStr: TStringStream;
begin
  InStr := TStringStream.Create(Input);
  try
    OutStr := TStringStream.Create('');
    try
      EncodeStream(InStr, OutStr);
      Result := OutStr.DataString;
    finally
      OutStr.Free;
    end;
  finally
    InStr.Free;
  end;
end;

此代码尚未针对Unicode更新。在不指定编码的情况下使用TStringStream InStr是问题所在。如果未指定编码,则ANSI用于解码为字节数组。因此,只能正确解码本地ANSI代码页中的字符。

DecodeString中的另一个方向犯了同样的错误。

您可以通过创建指定完整Unicode编码的变体来轻松解决此问题。例如:

function EncodeString(const Input: string): string;
var
  InStr, OutStr: TStringStream;
begin
  InStr := TStringStream.Create(Input, TEncoding.UTF8);
  try
    OutStr := TStringStream.Create('');
    try
      EncodeStream(InStr, OutStr);
      Result := OutStr.DataString;
    finally
      OutStr.Free;
    end;
  finally
    InStr.Free;
  end;
end;

function DecodeString(const Input: string): string;
var
  InStr, OutStr: TStringStream;
begin
  InStr := TStringStream.Create(Input);
  try
    OutStr := TStringStream.Create('', TEncoding.UTF8);
    try
      DecodeStream(InStr, OutStr);
      Result := OutStr.DataString;
    finally
      OutStr.Free;
    end;
  finally
    InStr.Free;
  end;
end;

只要它是完整的Unicode编码,您指定的编码无关紧要,并且您在两个方向上使用相同的编码!

显然应鼓励Embarcadero对其代码进行更改。

此程序演示了此修复程序的工作原理:

{$APPTYPE CONSOLE}

uses
  System.SysUtils, System.Classes, Soap.EncdDecd;

function EncodeString(const Input: string): string;
var
  InStr, OutStr: TStringStream;
begin
  InStr := TStringStream.Create(Input, TEncoding.UTF8);
  try
    OutStr := TStringStream.Create('');
    try
      EncodeStream(InStr, OutStr);
      Result := OutStr.DataString;
    finally
      OutStr.Free;
    end;
  finally
    InStr.Free;
  end;
end;

function DecodeString(const Input: string): string;
var
  InStr, OutStr: TStringStream;
begin
  InStr := TStringStream.Create(Input);
  try
    OutStr := TStringStream.Create('', TEncoding.UTF8);
    try
      DecodeStream(InStr, OutStr);
      Result := OutStr.DataString;
    finally
      OutStr.Free;
    end;
  finally
    InStr.Free;
  end;
end;

const
  N = 256;

var
  i: Integer;
  s1, s2: string;

begin
  SetLength(s1, N);
  for i := 1 to N do
    s1[i] := Chr(i-1);

  s2 := Soap.EncdDecd.EncodeString(s1);
  s2 := Soap.EncdDecd.DecodeString(s2);
  Writeln(s1=s2);

  s2 := EncodeString(s1);
  s2 := DecodeString(s2);
  Writeln(s1=s2);
end.

输出:

FALSE
TRUE

答案 1 :(得分:0)

快速修复:

ANSI对我来说已经足够了,因为编码后产生的文本必须尽可能短(易于通过电子邮件发送)。所以,我将我的ANSI字符串放入流中并对流进行编码/解码。它奏效了!


耶稣。一些文档(至少一条注释行)本来不错!