使用 delphi 2007 编码 base64 和解码 base64
Encode base64 and Decode base64 using delphi 2007
我必须在旧 Delphi 2007 上将字节数组编码为 base64 字符串(并解码该字符串)。
我该怎么办?
更多信息:
我试过突触(按照这里的建议Binary to Base64 (Delphi))。
Indy 附带 Delphi,并且有 TIdEncoderMIME
和 TIdDecoderMIME
类 用于处理 base64。例如:
uses
..., IdCoder, IdCoderMIME;
var
Bytes: TIdBytes;
Base64String: String;
begin
//...
Bytes := ...; // array of bytes
//...
Base64String := TIdEncoderMIME.EncodeBytes(Bytes);
//...
Bytes := TIdDecoderMIME.DecodeBytes(Base64String);
//...
end;
还有 encoding/decoding String
和 TStream
数据的方法。
更新:或者,如果您的版本没有上面显示的class
方法:
// TBytesStream was added in D2009, so define it manually for D2007
uses
..., IdCoder, IdCoderMIME
{$IF RTLVersion < 20)
, RTLConsts
{$IFEND}
;
{$IF RTLVersion < 20)
type
TBytesStream = class(TMemoryStream)
private
FBytes: TBytes;
protected
function Realloc(var NewCapacity: Longint): Pointer; override;
public
constructor Create(const ABytes: TBytes); overload;
property Bytes: TBytes read FBytes;
end;
constructor TBytesStream.Create(const ABytes: TBytes);
begin
inherited Create;
FBytes := ABytes;
SetPointer(Pointer(FBytes), Length(FBytes));
FCapacity := FSize;
end;
const
MemoryDelta = 00; // Must be a power of 2
function TBytesStream.Realloc(var NewCapacity: Integer): Pointer;
begin
if (NewCapacity > 0) and (NewCapacity <> FSize) then
NewCapacity := (NewCapacity + (MemoryDelta - 1)) and not (MemoryDelta - 1);
Result := Pointer(FBytes);
if NewCapacity <> FCapacity then
begin
SetLength(FBytes, NewCapacity);
Result := Pointer(FBytes);
if NewCapacity = 0 then
Exit;
if Result = nil then raise EStreamError.CreateRes(@SMemoryStreamError);
end;
end;
{$IFEND}
var
Bytes: TBytes;
BStrm: TBytesStream;
Encoder: TIdEncoderMIME;
Decoder: TIdDecoderMIME;
Base64String: String;
begin
//...
Bytes := ...; // array of bytes
//...
BStrm := TBytesStream.Create(Bytes);
try
Encoder := TIdEncoderMIME.Create;
try
Base64String := Encoder.Encode(BStrm);
finally
Encoder.Free;
end;
finally
BStrm.Free;
end;
//...
BStrm := TBytesStream.Create;
try
Decoder := TIdDecoderMIME.Create;
try
Decoder.DecodeBegin(BStrm);
Decoder.Decode(Base64String);
Decoder.DecodeEnd;
finally
Decoder.Free;
end;
Bytes := BStrm.Bytes;
finally
BStrm.Free;
end;
//...
end;
与您在问题中陈述的相反,EncdDecd
单位包含在 Delphi 2007 中。您可以简单地使用它。
这里是 EncodeToBase64:
uses
classes, sysutils;
function EncodeToBase64(var Buffer: TBytes): Longint;
const
EncodingTable: PChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var
WriteBuf: array[0..3] of Byte;
Buf: array[0..2] of Byte;
Dest: TMemoryStream;
i, j, Count: Integer;
begin
Result := 0;
Count := Length(Buffer);
j := Count div 3;
if j > 0 then
begin
Dest:= TMemoryStream.Create();
try
Dest.Position := 0;
for i := 0 to j - 1 do
begin
Move(Buffer[i * 3], Buf[0], 3);
WriteBuf[0] := Ord(EncodingTable[Buf[0] shr 2]);
WriteBuf[1] := Ord(EncodingTable[(Buf[0] and 3) shl 4 or (Buf[1] shr 4)]);
WriteBuf[2] := Ord(EncodingTable[(Buf[1] and 15) shl 2 or (Buf[2] shr 6)]);
WriteBuf[3] := Ord(EncodingTable[Buf[2] and 63]);
Dest.Write(WriteBuf, 4);
Inc(Result, 4);
Dec(Count, 3);
end;
if Count in [1, 2] then
begin
Move(Buffer[i * 3], Buf[0], Count);
WriteBuf[0] := Ord(EncodingTable[Buf[0] shr 2]);
WriteBuf[1] := Ord(EncodingTable[(Buf[0] and 3) shl 4 or (Buf[1] shr 4)]);
if Count = 1 then
WriteBuf[2] := Ord('=')
else
WriteBuf[2] := Ord(EncodingTable[(Buf[1] and 15) shl 2 or (Buf[2] shr 6)]);
WriteBuf[3] := Ord('=');
Dest.Write(WriteBuf, 4);
Inc(Result, 4);
Dec(Count, Count);
end;
if Result > 0 then
begin
SetLength(Buffer, Result);
Dest.Position := 0;
Dest.Read(Buffer[0], Result);
end;
finally
Dest.Free;
end;
end;
end;
这应该可以在没有任何特殊单元或组件的情况下工作。
David Heffernan 回复得很好!
在你的uses里加上class "EncdDecd",就会有程序:
function DecodeString (const Input: string): string;
function DecodeBase64 (const Input: string): TBytes;
使用 https://www.base64encode.org/
进行测试
Delphi 和站点中的字符串 "Working" 结果为:"V29ya2luZw =="
ShowMessage ('Working =' + EncodeString ('Working'));
ShowMessage ('Working =' + DecodeString ('V29ya2luZw =='));
对于 Delphi 的旧版本(在 Delphi XE7 之前),使用:
uses
Soap.EncdDecd
procedure DecodeFile(const Base64: AnsiString; const FileName: string);
var
BStream: TBytesStream;
begin
BStream := TBytesStream.Create(DecodeBase64(Base64));
try
BStream.SaveToFile(Filename);
finally
BStream.Free;
end;
end;
对于 Delphi 的新闻版本,使用:
uses
System.NetEncoding;
procedure DecodeFile(const Base64: String; const FileName: string);
var
BStream: TBytesStream;
begin
BStream:= TBytesStream.Create(TNetEncoding.Base64.DecodeStringToBytes(Base64));
try
BStream.SaveToFile(Filename);
finally
BStream.Free;
end;
end;
我必须在旧 Delphi 2007 上将字节数组编码为 base64 字符串(并解码该字符串)。 我该怎么办?
更多信息:
我试过突触(按照这里的建议Binary to Base64 (Delphi))。
Indy 附带 Delphi,并且有 TIdEncoderMIME
和 TIdDecoderMIME
类 用于处理 base64。例如:
uses
..., IdCoder, IdCoderMIME;
var
Bytes: TIdBytes;
Base64String: String;
begin
//...
Bytes := ...; // array of bytes
//...
Base64String := TIdEncoderMIME.EncodeBytes(Bytes);
//...
Bytes := TIdDecoderMIME.DecodeBytes(Base64String);
//...
end;
还有 encoding/decoding String
和 TStream
数据的方法。
更新:或者,如果您的版本没有上面显示的class
方法:
// TBytesStream was added in D2009, so define it manually for D2007
uses
..., IdCoder, IdCoderMIME
{$IF RTLVersion < 20)
, RTLConsts
{$IFEND}
;
{$IF RTLVersion < 20)
type
TBytesStream = class(TMemoryStream)
private
FBytes: TBytes;
protected
function Realloc(var NewCapacity: Longint): Pointer; override;
public
constructor Create(const ABytes: TBytes); overload;
property Bytes: TBytes read FBytes;
end;
constructor TBytesStream.Create(const ABytes: TBytes);
begin
inherited Create;
FBytes := ABytes;
SetPointer(Pointer(FBytes), Length(FBytes));
FCapacity := FSize;
end;
const
MemoryDelta = 00; // Must be a power of 2
function TBytesStream.Realloc(var NewCapacity: Integer): Pointer;
begin
if (NewCapacity > 0) and (NewCapacity <> FSize) then
NewCapacity := (NewCapacity + (MemoryDelta - 1)) and not (MemoryDelta - 1);
Result := Pointer(FBytes);
if NewCapacity <> FCapacity then
begin
SetLength(FBytes, NewCapacity);
Result := Pointer(FBytes);
if NewCapacity = 0 then
Exit;
if Result = nil then raise EStreamError.CreateRes(@SMemoryStreamError);
end;
end;
{$IFEND}
var
Bytes: TBytes;
BStrm: TBytesStream;
Encoder: TIdEncoderMIME;
Decoder: TIdDecoderMIME;
Base64String: String;
begin
//...
Bytes := ...; // array of bytes
//...
BStrm := TBytesStream.Create(Bytes);
try
Encoder := TIdEncoderMIME.Create;
try
Base64String := Encoder.Encode(BStrm);
finally
Encoder.Free;
end;
finally
BStrm.Free;
end;
//...
BStrm := TBytesStream.Create;
try
Decoder := TIdDecoderMIME.Create;
try
Decoder.DecodeBegin(BStrm);
Decoder.Decode(Base64String);
Decoder.DecodeEnd;
finally
Decoder.Free;
end;
Bytes := BStrm.Bytes;
finally
BStrm.Free;
end;
//...
end;
与您在问题中陈述的相反,EncdDecd
单位包含在 Delphi 2007 中。您可以简单地使用它。
这里是 EncodeToBase64:
uses
classes, sysutils;
function EncodeToBase64(var Buffer: TBytes): Longint;
const
EncodingTable: PChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var
WriteBuf: array[0..3] of Byte;
Buf: array[0..2] of Byte;
Dest: TMemoryStream;
i, j, Count: Integer;
begin
Result := 0;
Count := Length(Buffer);
j := Count div 3;
if j > 0 then
begin
Dest:= TMemoryStream.Create();
try
Dest.Position := 0;
for i := 0 to j - 1 do
begin
Move(Buffer[i * 3], Buf[0], 3);
WriteBuf[0] := Ord(EncodingTable[Buf[0] shr 2]);
WriteBuf[1] := Ord(EncodingTable[(Buf[0] and 3) shl 4 or (Buf[1] shr 4)]);
WriteBuf[2] := Ord(EncodingTable[(Buf[1] and 15) shl 2 or (Buf[2] shr 6)]);
WriteBuf[3] := Ord(EncodingTable[Buf[2] and 63]);
Dest.Write(WriteBuf, 4);
Inc(Result, 4);
Dec(Count, 3);
end;
if Count in [1, 2] then
begin
Move(Buffer[i * 3], Buf[0], Count);
WriteBuf[0] := Ord(EncodingTable[Buf[0] shr 2]);
WriteBuf[1] := Ord(EncodingTable[(Buf[0] and 3) shl 4 or (Buf[1] shr 4)]);
if Count = 1 then
WriteBuf[2] := Ord('=')
else
WriteBuf[2] := Ord(EncodingTable[(Buf[1] and 15) shl 2 or (Buf[2] shr 6)]);
WriteBuf[3] := Ord('=');
Dest.Write(WriteBuf, 4);
Inc(Result, 4);
Dec(Count, Count);
end;
if Result > 0 then
begin
SetLength(Buffer, Result);
Dest.Position := 0;
Dest.Read(Buffer[0], Result);
end;
finally
Dest.Free;
end;
end;
end;
这应该可以在没有任何特殊单元或组件的情况下工作。
David Heffernan 回复得很好!
在你的uses里加上class "EncdDecd",就会有程序:
function DecodeString (const Input: string): string;
function DecodeBase64 (const Input: string): TBytes;
使用 https://www.base64encode.org/
进行测试Delphi 和站点中的字符串 "Working" 结果为:"V29ya2luZw =="
ShowMessage ('Working =' + EncodeString ('Working'));
ShowMessage ('Working =' + DecodeString ('V29ya2luZw =='));
对于 Delphi 的旧版本(在 Delphi XE7 之前),使用:
uses
Soap.EncdDecd
procedure DecodeFile(const Base64: AnsiString; const FileName: string);
var
BStream: TBytesStream;
begin
BStream := TBytesStream.Create(DecodeBase64(Base64));
try
BStream.SaveToFile(Filename);
finally
BStream.Free;
end;
end;
对于 Delphi 的新闻版本,使用:
uses
System.NetEncoding;
procedure DecodeFile(const Base64: String; const FileName: string);
var
BStream: TBytesStream;
begin
BStream:= TBytesStream.Create(TNetEncoding.Base64.DecodeStringToBytes(Base64));
try
BStream.SaveToFile(Filename);
finally
BStream.Free;
end;
end;