我需要通过TCP协议从Windows发送到移动设备,iOS和Android,这是一个很大的Base64字符串
我没有问题发送和接收,但字符串大小太大,大约24000个字符,我正在寻找压缩解压缩这些字符串的方法。
我看,最好的方法是使用Zlib,我发现这些链接Delphi XE and ZLib Problems (II)解释了如何操作。
这些函数适用于普通文本字符串,但压缩base64字符串会使它们更大
我将发送的一个非常小的字符串的例子是:
cEJNYkpCSThLVEh6QjNFWC9wSGhXQ3lHWUlBcGNURS83TFdDNVUwUURxRnJvZlRVUWd4WEFWcFJBNUZSSE9JRXlsaWgzcEJvTGo5anQwTlEyd1pBTEtVQVlPbXdkKzJ6N3J5ZUd4SmU2bDNBWjFEd3lVZmZTR1FwNXRqWTVFOFd2SHRwakhDOU9JUEZRM00wMWhnU0p3MWxxNFRVdmdEU2pwekhwV2thS0JFNG9WYXRDUHhTdnp4blU5Vis2ZzJQYnRIdllubzhKSFhZeUlpckNtTGtUZHVHOTFncHVUWC9FSTdOK3JEUDBOVzlaTngrcEdxcXhpRWJ1ZXNUMmdxOXpJa0ZEak1ORHBFenFVSTlCdytHTy ==
我不知道压缩这种类型的字符串是否可行。我需要帮助
我使用的功能是:
uses
SysUtils, Classes, ZLib, EncdDecd;
function CompressAndEncodeString(const Str: string): string;
var
Utf8Stream: TStringStream;
Compressed: TMemoryStream;
Base64Stream: TStringStream;
begin
Utf8Stream := TStringStream.Create(Str, TEncoding.UTF8);
try
Compressed := TMemoryStream.Create;
try
ZCompressStream(Utf8Stream, Compressed);
Compressed.Position := 0;
Base64Stream := TStringStream.Create('', TEncoding.ASCII);
try
EncodeStream(Compressed, Base64Stream);
Result := Base64Stream.DataString;
finally
Base64Stream.Free;
end;
finally
Compressed.Free;
end;
finally
Utf8Stream.Free;
end;
end;
function DecodeAndDecompressString(const Str: string): string;
var
Utf8Stream: TStringStream;
Compressed: TMemoryStream;
Base64Stream: TStringStream;
begin
Base64Stream := TStringStream.Create(Str, TEncoding.ASCII);
try
Compressed := TMemoryStream.Create;
try
DecodeStream(Base64Stream, Compressed);
Compressed.Position := 0;
Utf8Stream := TStringStream.Create('', TEncoding.UTF8);
try
ZDecompressStream(Compressed, Utf8Stream);
Result := Utf8Stream.DataString;
finally
Utf8Stream.Free;
end;
finally
Compressed.Free;
end;
finally
Base64Stream.Free;
end;
end;
答案 0 :(得分:3)
据我所知,您已完成以下问题:
然后尝试压缩步骤3的输出并发现结果不小。这是可以预料的。您已经压缩了数据,并且不能期望进一步尝试压缩数据显着减小大小,特别是如果您同时使用base64编码则不会。如果你可以反复压缩数据并且每次都变得更小,那么最终就没有任何东西了。这显然是不可能的。
我认为你已经做得很好。您转换为UTF-8,对于大多数文本,它是Unicode编码中空间效率最高的。如果你使用中文文本,那么你最好使用UTF-16。然后压缩UTF-8,这也是合理的。最后,对于传输,您使用base64编码,也是合理的。
减少要传输的数据大小的最明显方法是省略base64步骤。如果您可以传输在步骤2中生成的压缩字节,那么您将减少传输。 Base64使用4个字节来编码3个字节,因此base64编码数据的大小比输入数据大三分之一。
另一种方法可能是使用比zlib更好的压缩算法,但同样可以实现的限制。通常以增加计算时间为代价实现更好的压缩。
答案 1 :(得分:0)
unit UFrmMain;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm2 = class(TForm)
Edit1: TEdit; //Password Text
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Button1: TButton;
Button2: TButton;
Memo1: TMemo; //Original Text
Memo2: TMemo; //Result Text
Label4: TLabel;
Label5: TLabel;
procedure Button1Click(Sender: TObject); //encrypt Button
procedure Button2Click(Sender: TObject); //decrypt Button
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
function EncriptarAES(Dato, Password: String): String;
function DesencriptarAES(Dato, Password: String): String;
function CompressAndEncodeString(const Str: string): string;
function DecodeAndDecompressString(const Str: string): string;
procedure OnIdle(Sender: TObject; var ADone: Boolean);
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
uses TntLXCryptoUtil, uTPLb_Codec,
uTPLb_BaseNonVisualComponent, uTPLb_CryptographicLibrary, ZLib, EncdDecd;
procedure TForm2.Button1Click(Sender: TObject);
begin
Memo2.Lines.Clear;
Memo2.Text := EncriptarAES(Memo1.Text, Edit1.Text);
end;
procedure TForm2.Button2Click(Sender: TObject);
begin
Memo1.Lines.Clear;
Memo1.Text := DesencriptarAES(Memo2.Text, Edit1.Text);
end;
function TForm2.CompressAndEncodeString(const Str: string): string;
var
Utf8Stream: TStringStream;
Compressed: TMemoryStream;
Base64Stream: TStringStream;
begin
Utf8Stream := TStringStream.Create(Str, TEncoding.UTF8);
try
Compressed := TMemoryStream.Create;
try
ZCompressStream(Utf8Stream, Compressed, TZCompressionLevel.zcMax);
Compressed.Position := 0;
Base64Stream := TStringStream.Create('', TEncoding.ASCII);
try
EncodeStream(Compressed, Base64Stream);
Result := Base64Stream.DataString;
finally
Base64Stream.Free;
end;
finally
Compressed.Free;
end;
finally
Utf8Stream.Free;
end;
end;
function TForm2.DecodeAndDecompressString(const Str: string): string;
var
Utf8Stream: TStringStream;
Compressed: TMemoryStream;
Base64Stream: TStringStream;
begin
Base64Stream := TStringStream.Create(Str, TEncoding.ASCII);
try
Compressed := TMemoryStream.Create;
try
DecodeStream(Base64Stream, Compressed);
Compressed.Position := 0;
Utf8Stream := TStringStream.Create('', TEncoding.UTF8);
try
ZDecompressStream(Compressed, Utf8Stream);
Result := Utf8Stream.DataString;
finally
Utf8Stream.Free;
end;
finally
Compressed.Free;
end;
finally
Base64Stream.Free;
end;
end;
function TForm2.DesencriptarAES(Dato, Password: String): String;
var
TextoPlano, TextoCodificado: String;
Codec: TCodec;
begin
TextoPlano := EmptyStr;
TextoCodificado := EmptyStr;
try
Codec := TCodec.Create(nil);
Codec.CryptoLibrary := TCryptographicLibrary.Create(Codec);
Codec.AsymetricKeySizeInBits := 1024;
Codec.StreamCipherId := 'native.StreamToBlock';
Codec.BlockCipherId := 'native.AES-256';
Codec.ChainModeId := 'native.CBC';
TextoCodificado := Dato;
Codec.Password := Password;
Codec.DecryptString(TextoPlano, TextoCodificado, TEncoding.UTF8);
TextoPlano := DecodeAndDecompressString(TextoPlano);
Codec.Free;
except on E: Exception do
begin
Codec.Free;
ShowMessage(e.ToString);
end;
end;
Result := TextoPlano;
end;
function TForm2.EncriptarAES(Dato, Password: String): String;
var
TextoPlano, TextoCodificado: String;
Codec: TCodec;
begin
TextoPlano := EmptyStr;
TextoCodificado := EmptyStr;
try
Codec := TCodec.Create(nil);
Codec.CryptoLibrary := TCryptographicLibrary.Create(Codec);
Codec.AsymetricKeySizeInBits := 1024;
Codec.StreamCipherId := 'native.StreamToBlock';
Codec.BlockCipherId := 'native.AES-256';
Codec.ChainModeId := 'native.CBC';
TextoPlano := Dato;
TextoPlano := CompressAndEncodeString(TextoPlano);
Codec.Password := Password;
Codec.EncryptString(TextoPlano, TextoCodificado, TEncoding.UTF8);
Codec.Free;
except on E: Exception do
begin
Codec.Free;
ShowMessage(e.ToString);
end;
end;
Result := TextoCodificado;
end;
procedure TForm2.FormCreate(Sender: TObject);
begin
Application.OnIdle := OnIdle;
end;
procedure TForm2.OnIdle(Sender: TObject; var ADone: Boolean);
begin
Label4.Caption := 'Longitud del Texto: '+IntToStr(Memo1.Lines.Text.Length);
Label5.Caption := 'Longitud del Texto: '+IntToStr(Memo2.Lines.Text.Length);
end;
end.
你认为有什么可以优化的吗?
现在,代码是,原始文本为3500个字符,占用2592个字符。
非常感谢你的帮助。