UTF-8字符串的base64编码

7

我有Rad Studio XE5。为了对输入字符串进行编码,我使用了Indy EncodeString函数...

我的代码如下:

procedure TForm5.Button2Click(Sender: TObject);
var
  UTF8: UTF8String;
begin
UTF8 := UTF8Encode(m1.Text);
m2.Text := ind.EncodeString(UTF8);
end;

但是对于UTF-8输入,输出结果是错误的。

orange  --> b3Jhbmdl  [correct]
book   --> Ym9vaw==   [correct]
سلام  -->  Pz8/Pw==   [wrong]
کتاب  --> Pz8/Pw==   [wrong]
دلفی  --> Pz8/Pw==   [wrong]

对于所有输入,使用utf-8编码后返回了相同的输出!!! 我的代码有什么问题?如何得到使用utf-8字符串进行base64编码的良好结果。


你使用Indy除了base64之外的功能吗? - David Heffernan
3
我使用了Indy库并解决了问题,只需阅读被接受的答案即可。 - peiman F.
1
我的观点是人们经常只是为了base64而使用Indy,但是有一种更简洁的方法可以获得base64,而不必使用Indy。当然,如果您正在使用Indy,则其base64代码是一个不错的选择。 - David Heffernan
3个回答

11

就像 @RRUZ 所说的那样,EncodeString() 希望您指定一个字节编码,将输入的 String 转换为该编码,然后将这些八位组编码为 base64。

您正在向 EncodeString() 传递一个 UTF8String,而 XE5 中它需要一个 UnicodeString 作为输入,因此 RTL 将会将 UTF8String 数据转换回 UTF-16,撤消您的 UTF8Encode()(顺便提一句,它已经被弃用了)。由于您没有指定字节编码,Indy 使用其默认编码,该编码默认设置为 ASCII(可以通过 IdGlobal 单元中的 GIdDefaultTextEncoding 变量进行配置)。

这就是为什么 orange 可以正常工作(没有数据丢失),但 سلام 失败(有数据丢失)的原因。

您需要彻底摆脱您的 UTF8String,让 Indy 为您处理 UTF-8:

procedure TForm5.Button2Click(Sender: TObject);
begin
  m2.Text := TIdEncoderMIME.EncodeString(m1.Text, IndyTextEncoding_UTF8);
end;

DecodeString()有一个类似的参数用于指定已经进行Base64编码的八位字节的字节编码方式。输入首先被解码成字节,然后使用指定的字节编码将字节转换为UnicodeString,例如:

procedure TForm5.Button3Click(Sender: TObject);
begin
  m1.Text := TIdDecoderMIME.DecodeString(m2.Text, IndyTextEncoding_UTF8);
end;

5

您需要调用EncodeString方法并传递正确的字节编码类。

尝试这样做:

m2.Text := TIdEncoderMIME.EncodeString(UTF8, IndyUTF8Encoding);

(IndyUTF8Encoding定义在IdGlobal单元中)

4
不要先将源String分配给UTF8String。将其原样传递到EncodeString(),并让Indy在将String内部转换为UTF-8之后再将八位字节编码为base64:m2.Text := TIdEncoderMIME.EncodeString(m1.Text, IndyUTF8Encoding);。 如果您使用的是D2007或更早版本,则EncodeString()需要一个额外的参数,该参数允许您指定String的ANSI编码,以便EncodeString()可以正确地将其转换为UTF-8。此外,请注意,自Indy 10.6起,IndyUTF8Encoding已被替换为IndyTextEncoding_UTF8 - Remy Lebeau

2

针对RadStudio10 C++的内容:

#include <IdGlobal.hpp> String my_str = L"Շնորհակալություն"; // 定义一个字符串变量 String str = IdEncoderMIME1->EncodeString(my_str ,IndyTextEncoding_UTF8()); // 将my_str字符串变量编码成MIME格式,并将结果存储在str变量中 my_str = IdDecoderMIME1->DecodeString(str ,IndyTextEncoding_UTF8()); // 从编码后的字符串变量str中解码出原始字符串,并将其存储在my_str变量中


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接