2017-10-09 106 views
0

我有一個Ansi字符串,我用它來存儲二進制數據 - 在0-255範圍內的字節(我知道它應該是一個字節數組左右,但它們之間差別不大)。
我想通過Indy MIME(TIdEncoderMIME.EncodeString/TIdDecoderMIME.DecodeString)傳遞這個「二進制字符串」,並獲得一個人類可讀的字符串。如何使用Indy Mime編碼二進制數據?

我認爲如果我使用IndyTextEncoding_8Bit編碼,Encode/DecodeString的輸出將是隻有ANSI字符的字符串。但是我錯了!

那麼,如何用Indy Mime編碼二進制數據(類似於application/octet-stream)?

回答

4

對二進制數據不要使用AnsiString

AnsiString不適合二進制數據的容器,特別是在像XE7這樣的Unicode環境中。代替使用正確的字節容器,如T(Id)BytesTMemoryStream

你不可錯過AnsiString原樣通過TId(Encoder|Decoder)MIME字符串方法,只有UnicodeString,所以隱含的RTL安思< - > Unicode轉換可能會損壞您的二進制數據。改爲使用面向二進制的方法((Encode|Decode)Bytes()(Encode|Decode)Stream())。他們的存在是有原因的。

話雖這麼說,印第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; 
+0

感謝。我將我的代碼轉換爲使用TIDBytes。有用。但有一個問題:爲什麼不應該使用AnsiString來存儲二進制數據? AnsiString只不過是一個字節數組而已。只要你不把它轉換成字符串,一切都應該沒問題。 – Ampere

+0

@mutex'AnsiString'不僅僅是一個字節數組。它還有一個相關的代碼頁,這就是當在傳遞'AnsiString'到'TIdEncoderMIME.EncodeString()''時傳遞'AnsiString'值時會導致二進制數據丟失/損壞的原因。另外,如果您需要將代碼遷移到移動設備,則「AnsiString」不可用(沒有第三方修補程序) –

相關問題