Base64转二进制(Delphi)

4
我使用了你回答的二进制转Base64函数:Binary to Base64 (Delphi)
我成功地将文件编码为Base64字符串并写入MsSQL2008数据库,但我想问一个问题: 如何使用EncdDecd.pas再次将此文件写入磁盘?

在被接受的答案中,它谈到了一个 DecodeBase64 函数。你看过它吗?如果是这样,你做到了什么程度,遇到了什么问题? - Jon Skeet
是的,我正需要它,但我不知道如何使用它。您能否编写一个函数,像接受的答案一样,将此文件从编码的base64中恢复并将其写入磁盘? - user1135768
3
你尝试了什么?你做到哪一步了?只靠别人告诉你代码,你不会学到太多东西。请自己动手尝试。 - Jon Skeet
我还没有尝试过,DecodeBase64函数中只有一个参数(输入:AnsiString)。我不知道如何将其转换回原始文件。我正在努力学习。 - user1135768
5个回答

19

像往常一样,David的回答足够了。虽然我忍不住想提供一个稍微不同的解决方案,使用一些最近Delphi版本中的好东西。

procedure DecodeFile(const base64: AnsiString; const FileName: string);
var
  stream: TBytesStream;
begin
  stream := TBytesStream.Create(DecodeBase64(base64));
  try
    stream.SaveToFile(Filename);
  finally
    stream.Free;
  end;
end;

6
这是一种更为简洁的做法。请继续不要抵制提供替代和更好答案的诱惑! - David Heffernan

7

这个函数将会接收一个base64编码的字符串,解码它,并将结果字节数组写入文件。

procedure DecodeToFile(const base64: AnsiString; const FileName: string);
var
  stream: TFileStream;
  bytes: TBytes;
begin
  bytes := DecodeBase64(base64);
  stream := TFileStream.Create(FileName, fmCreate);
  try
    if bytes<>nil then
      stream.Write(bytes[0], Length(Bytes));
  finally
    stream.Free;
  end;
end;

为了解释这里正在发生的事情,第一行
bytes := DecodeBase64(base64);

执行解码操作并将文件的解码二进制内容返回到TBytes变量中。TBytes只是一个字节数组。

下一步是创建文件。在Delphi中编写文件的惯用方式是使用流。在这种情况下,我们需要一个TFileStream

stream := TFileStream.Create(FileName, fmCreate);
fmCreate选项表示如果文件已经存在,它将被我们写的内容替换并覆盖。
最后一步是将字节数组的内容写入文件。
if bytes<>nil then
  stream.Write(bytes[0], Length(Bytes));

if bytes<>nil检查是为了处理base64字符串解码为空数组的情况。如果我们删除此检查,则在启用范围检查的情况下(应该这样做),以下行将导致运行时错误。调用stream.Write应该是不言自明的。


3

在研究 Soap.EncdDecd 后,我们可以找到更多平台无关的方法,因为它的 DecodeBase64 使用了来自 System.NetEncoding 的通用方法(没有 AnsiString)。

基于 Uwe 的示例:

uses
  ...
  System.Classes,
  System.NetEncoding;

...
procedure DecodeFile(const base64: String; const FileName: string);
var
  stream: TBytesStream;
begin
  stream := TBytesStream.Create(TNetEncoding.Base64.DecodeStringToBytes(base64));
  try
    stream.SaveToFile(Filename);
  finally
    stream.Free;
  end;
end;

2
uses
  Soap.EncdDecd;

function TForm1.EncodeFile(const FileName: string): AnsiString;
var
  MemStream: TMemoryStream;
begin
  MemStream := TMemoryStream.Create;
  try
    MemStream.LoadFromFile(Filename);
    Result := EncodeBase64(MemStream.Memory, MemStream.Size);
  finally
    MemStream.Free;
  end;
end;

function TForm1.DecodeFile(const base64: AnsiString): TBytesStream;
begin
 Result := TBytesStream.Create(DecodeBase64(base64));
end;

1
我有一个非常老的Delphi2006(v10.0.2558.35231 Update 2),需要解码base64 UTF8编码的输入字符串。我最终找到了方法,以下是一个示例供有兴趣的人参考。
  Uses
    IdCoderMIME; // Indy9
  var
    decoder: TIdDecoderMIME;
    str: WideString;
  - - - 

  decoder := TIdDecoderMIME.Create(nil);
  str := base64DecodeUTF8(decoder, b64sourcestr);
  decoder.Free;
  - - - 

  function base64DecodeUTF8(decoder:TIdDecoderMIME; str:String): WideString;
  var
    stream:TMemoryStream;
    utf8: UTF8String;
    //idx:Integer;
  begin
    stream := TMemoryStream.Create;
    try
      decoder.DecodeToStream(str, stream);
      setString(utf8, PChar(stream.Memory), stream.Size);
      Result := UTF8Decode(utf8);
      //for idx := 0 to stream.Size-1 do begin
      //  Writeln(PChar(stream.Memory)[idx] + ' ' + IntToStr(ORD(PChar(stream.Memory)      [idx])) );
      //end;
    finally
      stream.Free;
    end;
  end;

1
TIdDecoderMIME有一个静态的DecodeStream()方法,因此您不需要实例化一个TIdDecoderMIME对象。您可以删除decoder变量,并将decoder.DecodeToStream(str, stream);替换为TIdDecoderMIME.DecodeStream(str, stream);。或者,您可以使用静态的TIdDecoderMIME.DecodeString()方法,该方法具有用于指定二进制数据的字符集的参数,以及在将Unicode字符串转换为Ansi(仅限D2007及更早版本)时输出字符串的字符集的参数。 - Remy Lebeau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接