【问题标题】:How can I find the byte encoding of a TIBCO Rendezvous message?如何找到 TIBCO Rendezvous 消息的字节编码?
【发布时间】:2019-10-21 18:55:08
【问题描述】:

在我的 Java 应用程序中,我将 TIBCO RV 消息以字节形式归档到文件中。

我正在编写一个可以回放消息的小型实用程序。这样我就可以从字节中创建一个 TibrvMsg 对象,而无需解析文件并手动构造对象。

我遇到的问题是我正在读取在 Linux 机器上创建的文件,并试图在 Windows 机器上运行我的应用程序。由于文件写入的字符集不同,我收到一个错误。

所以现在,我要做的是将每条消息记录在一个特定的字符集 (UTF-8) 中,这样我就不用关心我在哪个平台上运行我的播放应用程序了。应用程序应该只读取文件就知道事先写入文件的字符集。我计划为此使用 java.nio 包,将字节从一个字符集转换为另一个字符集。

我是否需要知道 TIBRV 消息字节编码的字符集以进行转换?如果是这样,我怎样才能找到它?

【问题讨论】:

  • 继续前进并改变了我记录数据的方式。消息以键值对的形式出现,两者都是基于字符串的。我继续以 UTF-8 格式编写消息,并假设在转换过程中数据不会丢失。回放时,我将只解析键值对,并通过一一设置每个键值对来手动构建对象。这是目前最直接和最暴力的解决方案。谢谢大家的帮助。大家的回答让我大开眼界。

标签: java character-encoding nio tibco


【解决方案1】:

您正在获取不透明数据,并且看起来,它试图将其作为文本数据写入文件而不转义它的非文本部分(或者您将其作为原始字节写入,然后尝试读取它,就好像它是基于字符的,这是相同的问题)。 这从一开始就是有缺陷的。

不透明的数据应被视为无意义的,无需修改即可简单地存储,以回馈给知道如何处理它的 API。如果数据必须以文本形式存储,那么您必须无损将字节转换为文本。适当的编码是 base64 之类的东西。如果将其应用于原始二进制数据,则字符集编码意义上的编码不是无损的。

只需将文件中的字节存储为 bytes(不是字符)以及指示消息长度和发送主题的固定长度前缀就足以通过系统。

关于消息中任何基于文本的字段,如果编码很重要(我强烈建议在设计应用程序时通常避免这个问题),那么您在重播时会遇到与原始接收时间相同的问题是从源编码转换为所需的编码(希望使用完全相同的代码),所以这对于回放来说应该不是问题。

【讨论】:

    【解决方案2】:

    这可能与 Java 字符串编码有关,而不是 TIBRV。虽然文档中有这个:

    字符串和字符编码 -------------------------------------------------- ------------------------------ Rendezvous 软件在几个角色中使用字符串: * 消息字段内的字符串数据 * 字段名称 * 主题名称(以及其他相关的字符串不是 严格在消息内) * 经认证的交货通讯员姓名 * 组名(容错) 所有这些字符串(C 和有线格式)都使用字符 适合发件人的 ISO 区域设置的编码。例如, 美国是语言环境 en_US,并使用 Latin-1 字符 编码(也称为 ISO 8859-1);日本是语言环境 ja_JP,并使用 Shift-JIS 字符编码。 当两个程序在同一语言环境中交换消息时,字符串 总是正确的。但是,当消息发送方和接收方使用 不同的字符编码,接收程序必须转换 根据需要在编码之间。集合点软件不转换 自动地。 EBCDIC 有关 EBCDIC 环境中的字符串编码的信息, 见 tibrv_SetCodePages() 。

    所以您可能想查看机器的语言环境。

    【讨论】:

    • 是的,整个事情看起来就像个笑话。
    • RV 旨在以牺牲一些灵活性为代价提高速度(如果您关心实现自己的字段),几乎所有它的用户从不使用不同的编码,并且在任何地方都将所有内容保持在最基本的水平。跨度>
    • 每条消息额外增加三个用户/内核副本极大地提高了速度:)
    • 为什么要进行 3 次转换?当您收到消息回调时,所有数据都在用户空间中。如果您只想从网络缓冲区中获取您想要的内容,请删除 tibco 并自己滚动(也许是 LBM,但我发现这有点痛苦)。
    • 好吧,我的错误 - 四个,而不是三个 - 从发送方的内核到 rvd 以及从 rvd 到内核,然后在接收方也是如此。
    【解决方案3】:

    正如mailing list message 所表明的(诚然相当陈旧),人们对该网络协议的内部结构知之甚少。这可能会给你所追求的目标带来很大的挑战。

    也就是说,如果消息只是二进制数据块(从网络捕获),它们甚至不应该有字符集。 Charsets 用于文本数据,它很重要,因为单个字符可以以多种不同的方式编码。二进制数据不是由字符组成的,因此不可能存在这种意义上的编码。

    【讨论】:

    • 如果我获取消息字节并将它们写入文件会怎样。它们会以默认平台字符集编写吗?
    • 我会说你完全倒退了。文本数据没有字符集。 Charset 是将文本数据转换为字节流所需的,反之亦然。由于网络数据是字节流,因此您需要一个字符集来解释它包含的任何文本。
    【解决方案4】:

    我需要知道什么字符集 TIBRV 消息字节被编码为 转型?

    是的。字符集是一种将文本转换为字节流的方法,反之亦然。您的网络数据是一个字节流,因此当您将其部分解释为文本时,您是(隐式或显式)使用字符集 - 问题是它是否正确。

    将字节从一个字符集转换为另一个基本上意味着使用一个字符集将它们转换为文本,然后使用另一个字符集转换回字节。请注意,这可能会导致数据长度发生变化,因为许多字符集对某些字符使用超过 1 个字节。在网络消息的上下文中,当它使长度字段无效或导致文本字段溢出时,这可能会出现问题。最好不要进行任何转换,而是教阅读应用程序学习如何处理不同的字符集。

    如果是这样,我怎样才能找到它?

    查看协议规范。

    【讨论】:

      【解决方案5】:

      从 inputStream 中读取 byte[] 中的所有内容,将 byte[] 写入 FileOutputStream。

      不应该涉及读取器或写入器,它们会进行字符转换,这是错误的。

      在您了解 java.io 之前,请远离 java.nio。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-30
        • 1970-01-01
        • 1970-01-01
        • 2010-12-15
        • 1970-01-01
        • 2011-08-07
        相关资源
        最近更新 更多