4
votes

I used Binary to Base64 function that you answered : Binary to Base64 (Delphi)

I successfully encode a file to base64 string and write it to MsSQL2008 database, but i want to ask a question: How can i write this file to disk again with using EncdDecd.pas?

5
In the accepted answer, it talks about a DecodeBase64 function. Did you look at it? If so, how far did you get, and what problems did you run into? - Jon Skeet
Yes i am looking for it exactly but i dont know how to use it. Can you write a function like in accepted answer for restore this file from encoded base64 and writing it to disk? - user1135768
Again, what have you tried, how far have you got? You won't learn much by just being spoonfed code. - Jon Skeet
I have not tried, there is only one parameter in DecodeBase64 function (Input: AnsiString). I dont know how can i convert it to original file again. I trying to learn. - user1135768

5 Answers

17
votes

As always, David answered sufficiently. Although I can't resist to give a slightly different solution using some of the goodies from the recent Delphi versions.

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;
7
votes

This function will take a base64 encoded string, decode it, and write the resulting byte array to a file.

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;

To explain what is happening here, the first line

bytes := DecodeBase64(base64);

performs the decode and returns the decoded binary contents of the file in a TBytes variable. TBytes is simply an array of bytes.

The next step is to create the file. The idiomatic way to write files in Delphi is to use streams. In this case we want a TFileStream.

stream := TFileStream.Create(FileName, fmCreate);

The fmCreate option means that if the file already exists, it will be replaced and overwritten by what we write.

The final step is to write the contents of the byte array to the file

if bytes<>nil then
  stream.Write(bytes[0], Length(Bytes));

The if bytes<>nil check is to handle the case where the base64 string decodes to an empty array. If we were to remove that check then the following line would result in a runtime error if you were running with range checking enabled (which you should be doing). The call to stream.Write should be self-explanatory.

2
votes

After looking into Soap.EncdDecd the one can find more platform independent way, as it's DecodeBase64 uses universal (no AnsiString) methods from System.NetEncoding.

Based on Uwe's sample:

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;
1
votes

I have a very old Delphi2006(v10.0.2558.35231 Update 2) and had to decode base64 UTF8 encoded input strings. I finally figured it out and heres an example for anyone interested.

  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
votes
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;