如何使用 Indy Mime 对二进制数据进行编码?

WeG*_*ars 1 delphi encoding mime indy delphi-xe7

我有一个 Ansi 字符串,用于存储二进制数据 - 0-255 范围内的字节(我知道它应该是一个字节数组左右,但它们之间没有太大区别)。
我想通过 Indy MIME (TIdEncoderMIME.EncodeString / TIdDecoderMIME.DecodeString) 传递这个“二进制字符串”并获得人类可读的ANSI字符串。

我认为如果我使用 IndyTextEncoding_8Bit 编码,Encode/DecodeString 的输出将是一个仅包含 ANSI 字符的字符串。但是我错了!

那么,如何使用 Indy Mime 编码二进制数据(类似于application/octet-stream)?

Rem*_*eau 5

不要用于AnsiString二进制数据!

AnsiString不是二进制数据的合适容器,尤其是在像 XE7 这样的 Unicode 环境中。使用适当的字节容器,例如T(Id)BytesTMemoryStream

您无法按AnsiString 原样通过TId(Encoder|Decoder)MIME字符串方法传递,只能通过UnicodeString,因此隐式 RTL Ansi<->Unicode 转换可能会损坏您的二进制数据。请改用面向二进制的方法 ( (Encode|Decode)Bytes(), (Encode|Decode)Stream())。它们的存在是有原因的。

话虽这么说,Indy 10 确实有一个TIdMemoryBufferStream类(仅限桌面平台),因此如果您必须使用AnsiString(而且您确实不应该),您可以将其包装在TStream接口中,而无需在内存中制作额外的数据副本。例如:

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;
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)