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

WeG*_*ars 1 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;
Run Code Online (Sandbox Code Playgroud)

更新:
如果我做char(Random(128))而不是255,它可以工作!

Dav*_*nan 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;
Run Code Online (Sandbox Code Playgroud)

此代码尚未针对Unicode更新.在没有指定编码的情况下使用TStringStreamfor 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;
Run Code Online (Sandbox Code Playgroud)

只要它是完整的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.
Run Code Online (Sandbox Code Playgroud)

输出:

FALSE
TRUE

  • 也许这个代码应该提供给EMBT,这样他们就可以销售一个好产品;)David Heffernan可以获得一些免费许可来修复他们不关心的错误.就那么简单!@Marco Cantu - 我可以和大卫分开许可吗?谢谢 (3认同)