-3

TStringStream我在 a ( 或者它可以是任何)中有一些不错的或不太好的数据TStream,我想以最好的方式可视化,如果它包含文本,我想将它显示为文本,如果它不可能,我想显示十六进制代码。我知道没有可靠的方法可以可靠地说这是文本或二进制文件,但这不是目标,只是将其可视化以进行调试建议。

所以如果字符串

  • 只有Chars带有代码的字符,介于 32 和 127 之间,我可以接受它作为AnsiString. 这很容易实现
  • 如果没有,我会尝试将其转换为 Utf8String,因为我知道Utf8Stringformat,所以我可以决定它是否是有效的 utf8 字符串。所以我需要某种可以告诉我是的函数,它可以是 utf8string。如果我错了,谁在乎,如果它是不可读的文本,那不是问题,我也不能流利地阅读十六进制代码。
  • 如果还是不行,我想把它解释为宽字符串,这是最难的部分,因为据我所知它没有任何格式,所以我需要在这里猜测很多,这需要最大的创造力. 如果这完全是不可能完成的任务,那就跳过这一点。但说我不期待汉字。
  • else:显示十六进制代码。

我完全重写了我的问题,因为每个人都在评论这样一个事实,即数据来自哪里,以及我应该如何定义协议(我也得到了有用的提示,谢谢),这并没有让我更接近解决我的问题问题,希望在新问题中得到更好的描述。

4

3 回答 3

1

所以如果字符串

•只有字符字符的代码,介于 32 和 127 之间,我可以接受它作为 AnsiString。这很容易实现

是的。但是,128 到 255 之间的字符值(也称为 ANSI/MBCS 字符)也可以存储在 an 中AnsiString并以可视方式显示,但您必须知道这些值所属的原始字符集。对于 D2009+,您可以将值存储到 a 中RawByteString并使用该SetCodePage()函数将适当的代码页与字符串相关联。这样,当您在代码周围传递字符串时,字符会被正确解释。如果您不关心 Unicode 格式之外的非 ASCII 字符,那么您可以忽略这一点。

• 如果不是,我会尝试将其转换为 Utf8String,因为我知道 Utf8String 具有格式,所以我可以决定它是否是有效的 utf8 字符串。所以我需要某种可以告诉我是的函数,它可以是 utf8string。

要检查数据是否为有效的 UTF-8 字符串,您可以使用 Win32 APIWindows.MultiByteToWideChar()函数或 Embarcadero 的System.LocaleCharsToUnicode()函数(仅限 XE 及更高版本)。指定CP_UTF8(65001) 代码页、MB_ERR_INVALID_CHARS标志和nil输出缓冲区。如果数据是有效的 UTF-8 字符串,则函数将返回数据在实际解码时可以产生的 UTF-16 字符数。否则,该函数将失败并显示ERROR_NO_UNICODE_TRANSLATION错误代码。

另一种选择(仅限 D2009 及更高版本)是使用类的GetCharCount()方法SysUtils.TEncoding.UTF8来计算相同数量的 UTF-16 字符。

•如果仍然不是这样,我想将其解释为宽字符串,这是最难的部分,因为据我所知它没有任何格式

是的,当然可以 - UTF-16,它与 UTF-8 一样是一种已定义的格式(事实上,UTF-16 有两种风格,小端和大端)。

要检查数据是否为有效的 UTF-16(仅限小端)字符串,您可以使用 Win32 APIWindows.WideCharToMultiByte()函数或 Embarcadero 的System.UnicodeToLocaleChars()函数(仅限 XE 及更高版本)。指定CP_UTF8(65001) 代码页、WC_ERR_INVALID_CHARS标志和nil输出缓冲区。如果数据是有效的 UTF-16LE 字符串,则函数将返回数据在实际编码时可以产生的 UTF-8 字节数。否则,该函数将失败并显示ERROR_NO_UNICODE_TRANSLATION错误代码。

另一种选择(仅限 D2009 及更高版本)是使用(little endian) 或类的GetByteCount()方法来计算相同数量的 UTF-8 字节。SysUtils.TEncoding.UnicodeSysUtils.TEncoding.BigEndianUnicode

所以我需要在这里猜测很多

不,你没有。对于 UTF-8 和 UTF-16,不涉及猜测。它们是定义明确的标准化格式,它们旨在相互转换而不会丢失任何数据。

于 2012-10-30T17:23:30.977 回答
0

我强烈建议定义一个协议并坚持下去。例如,定义所有文本都是 UTF8 格式,因此在 Delphi 7 中您可以使用 UTF8Encode/UTF8Decode 和在 XE2 中使用 UTF8ToWideString(节省带宽!),并且每条消息都有一个定义它的标题(例如二进制)以及它有多长,因此您知道在数据之后您可以将下一条消息或文本恢复为 UTF8。

于 2012-10-29T22:24:08.110 回答
0

您无法实施防弹验证。除非您有一些外部限制,否则可以作为字符串传递 - WideString 的任何字符也将是 AnsiString 中的有效字符对。所以你必须在字符串之前传递一些标记。

  • 对于 unicode 字符串,通常在流开始时会发送一个特殊的“字母”:http ://en.wikipedia.org/wiki/Byte_order_mark这不是防弹的,但是 AnsiString 的第一个和第二个字符的机会非常低 -虽然仍有可能。
  • 您可以约定,第一个两个字节将是 Windows 代码页,然后使用 TEncoding 进一步将字节转换为字符串。然而,这将使未来与非 Windows 系统的交互变得相当困难。
  • 您可以在主要加载之前将Internet 标准编码作为 AnsiString 标记传递,就像在 URLs 中所做的那样。该标记将仅使用 7 位 ASCII 值,因此从流中获取它是安全的。然而,这些字符集名称中有很多同义词,因此您必须使用这些同义词名称查询一些字典。
于 2012-10-30T06:22:20.107 回答