【问题标题】:How to encode binary data with Indy Mime?如何使用 Indy Mime 对二进制数据进行编码?
【发布时间】:2018-03-20 21:14:13
【问题描述】:

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

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

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

【问题讨论】:

    标签: delphi encoding mime indy delphi-xe7


    【解决方案1】:

    不要将AnsiString 用于二进制数据!

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

    您不能通过TId(Encoder|Decoder)MIME 字符串方法传递AnsiString 原样,只能通过UnicodeString,因此隐式RTL AnsiUnicode 转换可能会损坏您的二进制数据.请改用面向二进制的方法((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;
    

    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;
    

    【讨论】:

    • 谢谢。我将我的代码转换为使用 TIDBytes。有用。但是有一个问题:为什么不应该使用 AnsiString 来存储二进制数据? AnsiString 只不过是一个字节数组(嗯....几乎“仅此而已”)。只要您不将其转换为字符串,一切都应该没问题。
    • @mutex AnsiString 不仅仅是一个字节数组。它还有一个关联的代码页,这就是在不小心传递AnsiString 值时可能导致二进制数据丢失/损坏的原因,就像您将AnsiString 传递给TIdEncoderMIME.EncodeString() 时所做的那样。此外,如果您需要将代码迁移到移动设备,AnsiString 不可用(没有第 3 方补丁)
    猜你喜欢
    • 2013-07-05
    • 2014-04-08
    • 1970-01-01
    • 2010-10-26
    • 2012-01-08
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    • 2014-08-09
    相关资源
    最近更新 更多