C# 关于可以是ASCII或UTF-16的封送字符串的建议

C# 关于可以是ASCII或UTF-16的封送字符串的建议,c#,compact-framework,character-encoding,internationalization,utf-16,C#,Compact Framework,Character Encoding,Internationalization,Utf 16,欢迎来到unsafeland 我正在对一个遗留库执行p/Invoke,该库以未知长度的非托管字节缓冲区的形式为我提供一个以0结尾的C样式字符串,该缓冲区可以是ASCII或UTF-16,但不提供任何指示-字节流本身除外,它是 现在我有一个糟糕的方案,基于检查单字节和双字节0字节,来决定是否应该从Char*或SByte*创建一个托管字符串。对于高于U+00FF的每个Unicode码点,该方案显然都会崩溃 这就是我所拥有的: 非托管字节缓冲区的地址 非托管字节缓冲区的长度未知 非托管字节缓冲区是以0

欢迎来到
unsafe
land

我正在对一个遗留库执行p/Invoke,该库以未知长度的非托管字节缓冲区的形式为我提供一个以0结尾的C样式字符串,该缓冲区可以是ASCIIUTF-16,但不提供任何指示-字节流本身除外,它是

现在我有一个糟糕的方案,基于检查单字节和双字节0字节,来决定是否应该从
Char*
SByte*
创建一个托管
字符串。对于高于
U+00FF
的每个Unicode码点,该方案显然都会崩溃

这就是我所拥有的:

  • 非托管字节缓冲区的地址
  • 非托管字节缓冲区的长度未知
  • 非托管字节缓冲区是以0结尾的ASCII C样式字符串或以0结尾的UTF-16 C样式字符串
这就是我想要的:

  • 从非托管字节缓冲区(无论是ASCII还是UTF-16)创建正确的托管
    字符串

这个问题一般是可以解决的吗?

一种向天真的编码检测方案添加一级启发式的方法,该方案基于检查单字节和双字节0字节:

  • 假设来自遗留库的封送“上下文”由一个或多个字符串组成
  • 如果这种上下文中的一个字符串可能是UTF-16,那么该上下文中的所有其他字符串也都是UTF-16
  • 因此,一旦发现具有“足够高”确定性的UTF-16字符串,所有其他检测都将“可能是UTF-16”
  • 如果发现“可能不是UTF-16”字符串是“绝对不是UTF-8”字符串,那么它也不能是ASCII,所以将其设置为UTF-16

  • 这将提供更高的准确创建托管
    字符串的比率。

    我认为这不能100%解决。如果缓冲区包含6C3400(“l4”),那么这是表示水的中文符号,还是只是一个较低的ASCII L和4?但是,根据具体的字符串,“大部分时间”应该可以猜对

    UTF-16是小端数还是(可能)大端数

    最大的风险是缓冲区溢出。例如,如果缓冲区以00开头,那是长度为零的ASCII字符串,还是我们应该尝试准备更多的缓冲区,将其解释为UTF-16BE

    这个问题一般是可以解决的吗

    没有

    如果您知道字符串的长度(并且是偶数),则可以通过存在00字节填充ISO-8859-1字符来识别UTF-16。(即使是非拉丁字母语言也会大量使用ASCII空格和换行符。)


    但是如果你依赖于空终止,那对你没有帮助。如果查找00 00,可以间接匹配正好位于空终止符后面的00字节。更糟糕的是,如果in ASCII字符串不是以双null结尾的,则您将直接运行到字符串的末尾。

    旧库不会以任何方式(如BOM或其他方式)指示编码。@ctacke:no。太棒了,嗯!?:-)