【问题标题】:Encode base64 and Decode base64 using delphi 2007使用delphi 2007编码base64和解码base64
【发布时间】:2015-07-14 10:39:16
【问题描述】:

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

更多信息:

我已经尝试过突触(这里建议Binary to Base64 (Delphi))。

【问题讨论】:

  • Base64 是一种标准编码,与语言或版本无关。这意味着它的编码或解码方式有问题。我们可以看看你的代码吗?
  • 你可以使用 Indy 试试 TIdDecoderMIME 类。
  • 还有TIdEncoderMIME
  • EncdDecd.pas 不在 $(DELPHI)\Source\Internet 路径中?
  • @Jerry Dodge:你说得对,尝试一个小例子,突触库函数似乎按预期工作。我的代码应该有问题(或特殊情况),我会检查一下。

标签: delphi encoding base64 decoding delphi-2007


【解决方案1】:

对于旧版本的 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 的 NEWS 版本,请使用:

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;

【讨论】:

    【解决方案2】:

    大卫赫弗南反应很好!

    在你的使用中添加“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 =='));
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        Indy 与 Delphi 一起提供,并具有用于处理 base64 的 TIdEncoderMIMETIdDecoderMIME 类。例如:

        uses
          ..., IdCoder, IdCoderMIME;
        
        var
          Bytes: TIdBytes;
          Base64String: String;
        begin
          //...
          Bytes := ...; // array of bytes
          //...
          Base64String := TIdEncoderMIME.EncodeBytes(Bytes);
          //...
          Bytes := TIdDecoderMIME.DecodeBytes(Base64String);
          //...
        end;
        

        还有编码/解码StringTStream数据的方法。

        更新:或者,如果您的版本没有上面显示的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 = $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;
        

        【讨论】:

        • 它在进一步的 delphi 版本上运行良好!感谢您的建议和示例,我会尽快在 Delphi 2007 上进行检查,但我想它也适用于旧 ide。
        • @Hwau:你可以将 Indy 升级到最新版本,即使在旧的 Delphi 上也是如此
        • 不幸的是,使用 Delphi2007 未声明 EncodeBytes 和 DecodeBytes 函数。我宁愿不要手动升级 indy,还有其他方法吗?
        • @Hwau:您必须查看 D2007 的 IdCoder 单元,看看该版本中实际可用的功能。更糟糕的情况是,class 方法可能不可用,因此请尝试实例化TIdEncoderMIME/TIdDecoderMIME 对象并改用它们的非class 方法。我用一个例子更新了我的答案。
        • @RemyLebeau:很抱歉长时间的沉默,TBytesStream 似乎在 Delphi-2007 中未定义,我还能如何将字节数组加载到流中?
        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-12-17
          • 2015-04-18
          • 2011-05-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多