【问题标题】:How to send text in UTF-8 using Indy TIdTCPServer in c++ builder如何在 c++ builder 中使用 Indy TIdTCPServer 以 UTF-8 发送文本
【发布时间】:2011-03-18 04:43:02
【问题描述】:

我的客户端 j2me 应用程序使用 UTF-8 读取文本输入流

reader = new InputStreamReader(in,"UTF-8");

我的服务器在连接时使用此语句发送文本

AContext->Connection->IOHandler->WriteLn(cxMemo1->Text,TEncoding::UTF8);

但结果文本显示奇怪的字符,如??????????????????????????? ???????????????

我哪里做错了?

当我尝试以这种方式从 utf-8 编码数据文件加载时

AContext->Connection->IOHandler->WriteFile("c:\\fids.xml");

都是一样的!

【问题讨论】:

    标签: sockets java-me character-encoding indy10


    【解决方案1】:

    Indy 10 完全支持 UTF-8 编码。我自己使用它的 TIdFTP 组件并成功上传了 Unicode 文本文件。据我所知:

    1. 您的连接/传输类型设置为ftASCII,而不是ftBinary
    2. 您的 J2ME 小程序/主机平台不支持 UTF-8

    【讨论】:

    • 我使用以下代码String URL="socket://"+ServerIP+":"+ServerPort; socket=(StreamConnection)Connector.open(URL);进行了连接
    • 我知道这些强大的组件比我想象的要多得多,但问题是我在这里做错了。
    • 编辑:我想更改我原来的帖子,Indy 仍在开发如何有效地处理 Unicode(由 Remy 提供)。您可能想尝试使用 Write()。
    • TransferType 仅适用于TIdFTP 组件,不适用于TIdTCPServer 组件。
    • 无论如何@nbaztec 我正在使用LWUIT!它支持 UTF-8 吗?我google了一下,还没找到!
    【解决方案2】:

    '?'当数据通过 Unicode 到 Ansi 转换为不支持正在转换的 Unicode 字符的 Ansi 字符集时,就会出现字符。

    您使用的是哪个版本的 C++Builder?在 CB2009 之前的版本中,您应该告诉 Indy 您传入的 AnsiString 数据的编码。对于大多数基于字符串的操作,Indy 默认为 ASCII(即:TIdTextEncoding::ASCII)。可以在需要时使用可选的AAnsiEncoding 参数、TIdIOHandler::DefAnsiEncoding 属性或全局Idglobal::GIdDefaultAnsiEncoding 设置来覆盖它。如果未指定正确的编码,则 AnsiString 数据在转换为 UTF-8 之前可能无法正确转换为 Unicode。例如:

    AContext->Connection->IOHandler->WriteLn(cxMemo1->Text, TIdTextEncoding_UTF8, TTIdTextEncoding_Default);
    

    或者:

    AContext->Connection->IOHandler->DefAnsiEncoding = TIdTextEncoding_Default;
    AContext->Connection->IOHandler->WriteLn(cxMemo1->Text, TIdTextEncoding_UTF8);
    

    如果您不想在每次调用时指定 UTF-8 编码,您也可以选择使用 TIdIOHandler::DefStringEncoding 属性:

    AContext->Connection->IOHandler->DefStringEncoding = TIdTextEncoding_UTF8;
    AContext->Connection->IOHandler->WriteLn(cxMemo1->Text);
    

    现在,话虽如此,WriteFile() 也在发送 J2ME 未正确处理的数据这一事实告诉我,Indy 不是问题的根源。 WriteFile() 只是将原始文件数据原样复制到连接中,根本没有任何解释。如果您发送一个 UTF-8 编码的文件,那么 UTF-8 编码的八位字节将被发送到 J2ME。

    我建议您使用数据包嗅探器(例如 Wireshark)来验证 Indy 发送的数据。这将确定 Indy 是否真的有过错。

    *PS:请注意,在上面的示例中,我直接使用 Indy 的 TIdTextEncoding 宏而不是 TEncoding。这是因为 Indy 的 TIdTextEncoding 逻辑可以解决 Embarcadero 的 TEncoding 类中的一些错误。此外,我们将在 Indy 11 中逐步停止对 TEncoding 的直接支持,并扩展 TIdTextEncoding,因此 Indy 拥有比 Embarcadero 提供的更多控制权。

    【讨论】:

    • 嗨@Remy 我正在使用 C++ Builder 2010!
    • 这种方式也无济于事try { int b=AContext->Connection->IOHandler->ReadByte(); result->Items->Add(b); //AContext->Connection->IOHandler->WriteFile("c:\\fids.xml"); AContext->Connection->IOHandler->DefStringEncoding = TIdTextEncoding::UTF8; AContext->Connection->IOHandler->Write(cxMemo1->Text); AContext->Connection->Disconnect(); } catch(Exception & e) { //ShowMessage(e.ToString()); AContext->Connection->Disconnect(); }
    • 您所做的只是添加一个对IOHandler->ReadByte() 的调用,关于如何将数据发送回J2ME,您没有更改任何其他内容。您仍然需要找出问题的根本原因。您是否按照我的建议执行并验证了原始传输数据?无论如何,我知道Write(UnicodeString, TIdTextEncoding::UTF8) 在 CB2010 中可以正常工作,因为那是我自己使用的版本。顺便说一句,像您一样直接在 TIdTCPServer 事件处理程序中读取 cxMemo1->Text 属性不是线程安全的,因此这本身可能是一个因素。
    • 我使用了便携式 Wireshark,但无法输入正确的过滤器以仅显示发送的所需数据包,然后我分配了袜子,但我认为我的捕获混淆了。
    • 您知道您的服务器正在侦听的 IP/端口,您可以对其进行过滤。或者简单地找到您识别数据的单个数据包,然后右键单击它并选择“Follow Stream”以查看仅针对该连接的所有数据包。
    猜你喜欢
    • 1970-01-01
    • 2019-07-01
    • 2012-04-08
    • 1970-01-01
    • 2012-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多