Reputation: 21154
I have an Ansi string that I use to store binary data - bytes in 0-255 range (I know it should be a Byte array or so, but it is not much difference between them).
I want to pass this "binary string" through Indy MIME (TIdEncoderMIME.EncodeString / TIdDecoderMIME.DecodeString) and obtain a human-readable ANSI string.
I thought that the output of Encode/DecodeString will be a string that has only ANSI characters in it if I use IndyTextEncoding_8Bit encoding. But I was wrong!
so, how to encode binary data with Indy Mime (something similar to application/octet-stream)?
Upvotes: 1
Views: 1710
Reputation: 596582
DONT use AnsiString
for binary data!
AnsiString
is not an appropriate container for binary data, especially in a Unicode environment like XE7. Use a proper byte container, like T(Id)Bytes
or TMemoryStream
instead.
You can't pass AnsiString
as-is through the TId(Encoder|Decoder)MIME
string methods, only UnicodeString
, so implicit RTL Ansi<->Unicode conversions are likely to corrupt your binary data. Use the binary-oriented methods instead ((Encode|Decode)Bytes()
, (Encode|Decode)Stream()
). They exist for a reason.
That being said, Indy 10 does have a TIdMemoryBufferStream
class (desktop platforms only), so if you MUST use AnsiString
(and you really shouldn't), you can wrap it in a TStream
interface without having to make additional copies of data in memory. For example:
var
Binary: AnsiString;
Strm: TIdMemoryBufferStream;
Base64: String;
begin
Binary := ...; // binary data
Strm := TIdMemoryBufferStream.Create(PAnsiChar(Binary), Length(Binary));
try
Base64 := TIdEncoderMIME.EncodeStream(Strm);
finally
Strm.Free;
end;
// use Base64 as needed...
end;
var
Base64: String;
Strm: TIdMemoryBufferStream;
Binary: AnsiString;
begin
Base64 := ...; // encoded data
SetLength(Binary, (Length(Base64) div 4) * 3);
Strm := TIdMemoryBufferStream.Create(PAnsiChar(Binary), Length(Binary));
try
TIdDecoderMIME.DecodeStream(Base64, Strm);
SetLength(Binary, Strm.Size);
SetCodePage(PRawByteString(@Binary)^, 28591, False);
finally
Strm.Free;
end;
// use Binary as needed...
end;
Upvotes: 6