使用delphi 2007编码base64并解码base64

使用delphi 2007编码base64并解码base64,delphi,encoding,base64,decoding,delphi-2007,Delphi,Encoding,Base64,Decoding,Delphi 2007,我必须在旧的Delphi2007上将字节数组编码为base64字符串(并解码该字符串)。 我怎么办 更多信息: 我已经尝试过synapse(如这里所建议的)。Indy随Delphi提供,并且有TidEncoderMie和TidDecoderMie类用于处理base64。例如: uses ..., IdCoder, IdCoderMIME; var Bytes: TIdBytes; Base64String: String; begin //... Bytes := ...;

我必须在旧的Delphi2007上将字节数组编码为base64字符串(并解码该字符串)。 我怎么办

更多信息:


我已经尝试过synapse(如这里所建议的)。

Indy随Delphi提供,并且有
TidEncoderMie
TidDecoderMie
类用于处理base64。例如:

uses
  ..., IdCoder, IdCoderMIME;

var
  Bytes: TIdBytes;
  Base64String: String;
begin
  //...
  Bytes := ...; // array of bytes
  //...
  Base64String := TIdEncoderMIME.EncodeBytes(Bytes);
  //...
  Bytes := TIdDecoderMIME.DecodeBytes(Base64String);
  //...
end;
也有编码/解码
字符串
TStream
数据的方法

更新:或者,如果您的版本没有上面显示的
方法:

// 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 = $2000; // 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;
//在D2009中添加了TBytesStream,因此请为D2007手动定义它
使用
…,IdCoder,IdCoderMIME
{$IF RTLVersion<20)
,RTLConsts
{$IFEND}
;
{$IF RTLVersion<20)
类型
TBytesStream=类(TMemoryStream)
私有的
FBytes:TBytes;
受保护的
函数Realloc(var NewCapacity:Longint):指针;重写;
公众的
构造函数创建(const ABytes:TBytes);重载;
属性字节:TBytes读取FBytes;
结束;
构造函数TBytesStream.Create(constabytes:TBytes);
开始
继承创造;
FBytes:=ABytes;
SetPointer(指针(字节)、长度(字节));
F容量:=F大小;
结束;
常数
MemoryDelta=$2000;//必须是2的幂
函数TBytesStream.Realloc(var NewCapacity:Integer):指针;
开始
如果(NewCapacity>0)和(NewCapacity FSize),则
新容量:=(新容量+(MemoryDelta-1))和非(MemoryDelta-1);
结果:=指针(FBytes);
如果是新产能,那么
开始
设置长度(FBytes,新容量);
结果:=指针(FBytes);
如果NewCapacity=0,则
出口
如果结果=nil,则引发EStreamError.CreateRes(@SMemoryStreamError);
结束;
结束;
{$IFEND}
变量
字节:TBytes;
BStrm:tbytestream;
编码器:TIdEncoderMIME;
解码器:tidrodecrime;
Base64String:字符串;
开始
//...
字节:=…;//字节数组
//...
BStrm:=TBytesStream.Create(字节);
尝试
编码器:=TIdEncoderMIME.Create;
尝试
Base64String:=编码器.Encode(BStrm);
最后
编码器。免费;
结束;
最后
免费;
结束;
//...
BStrm:=tbytestream.Create;
尝试
解码器:=TIdDecoderMIME.Create;
尝试
解码开始(BSTR);
解码器。解码(Base64String);
解码器.DecodeEnd;
最后
解码器。免费;
结束;
字节:=BStrm.Bytes;
最后
免费;
结束;
//...
结束;

与您在问题中所述相反,Delphi 2007中包含了
EncdDecd
单元。您可以简单地使用它。

这里是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; 

这应该可以在没有任何特殊装置或组件的情况下工作。

大卫·赫弗南反应非常好

在您使用的类“EncdDecd”中添加,它将具有以下步骤:

function DecodeString (const Input: string): string;
function DecodeBase64 (const Input: string): TBytes;
测试

Delphi和站点中的字符串“Working”导致:“V29ya2luZw==”


对于旧版本的Delphi(在Delphi XE7之前),请使用:

对于Delphi的新闻版本,请使用:

uses
System.NetEncoding;

Base64是一种标准编码,不分语言或版本。这意味着它的编码或解码方式都有问题。我们可以同时查看您的代码吗?您可以使用Indy尝试
TidDecoderMie
类。并且
TidEncoderMie
Encdecd.pas不在$(DELPHI)中\Source\Internet path?@Jerry Dodge:你说得对,试着用一个小例子,synapse lib函数似乎按预期工作。我的代码中应该有错误(或某个特定情况),我会检查这个。它在以后的delphi版本上运行良好!感谢您的建议和示例,我会尽快在delphi 2007上检查这个,但我想它在旧的ide上也可以运行。@Hwau:您可以将Indy升级到最新版本,即使在旧的delphi上也是如此。幸运的是,EncodeBytes和DecodeBytes函数没有使用Delphi2007声明。I如果你不想手动升级indy,还有其他方法吗?@Hwau:你必须查看D2007的
IdCoder
单元,看看该版本中实际有哪些功能可用。更糟糕的是,
class
方法可能不可用,所以试着实例化
tidecodermie
/
tidecodermie
对象and使用他们的非
方法。我用一个例子更新了我的答案。@RemyLebeau:很抱歉长时间的沉默,TBytesStream在Delphi-2007中似乎没有定义,否则我如何将字节数组加载到流中?
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;
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;