检查TStringStream的内容

时间:2012-10-29 22:10:29

标签: string delphi binary

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

所以如果是字符串

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

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

3 个答案:

答案 0 :(得分:1)

  

所以如果是字符串

     

•只有字符Chars,代码在32到127之间,我可以接受它作为AnsiString。它很容易实现

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

  

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

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

另一个选项(仅限D2009及更高版本)是使用GetByteCount()(小端)或SysUtils.TEncoding.Unicode类的SysUtils.TEncoding.BigEndianUnicode方法来计算相同数量的UTF-8字节。

  

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

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

  • 对于unicode字符串,通常会在流开始时发送一个特殊的“字母”:http://en.wikipedia.org/wiki/Byte_order_mark这不是防弹的,但AnsiString为第1和第2个字符设置的可能性非常低 - 尽管仍有可能。< / LI>
  • 你可以制定约定,前两个字节是Windows代码页,然后使用TEncoding进一步将字节转换为字符串。然而,这将使未来与非Windows系统的交互变得相当困难。
  • 您可以在主要加载之前将internet-standard encoding作为AnsiString标记传递,例如it is done in URLs。该标记仅使用7位ASCII值,因此从流中获取它是安全的。然而,这些字符集名称中有很多同义词,因此您必须使用这些同义词名称查询某些字典。