用于可视化的1:1 UTF-8八位字节解码

时间:2014-06-13 21:51:33

标签: c# .net unicode utf-8

我正在制作一个工具(C#,WPF)来查看可能包含嵌入文本的二进制数据。传统的数据查看器使用两个垂直列,一个显示每个字节的十六进制值,另一个显示与每个字节对应的ASCII字符(如果可打印)。

我一直认为支持使用非ASCII编码显示嵌入文本会很好,特别是UTF-8和UTF-16。问题是UTF代码点没有用八位字节映射1:1。我想根据数据中的位置保持输出网格对齐,因此我需要每个八位字节映射到某些以显示在网格中的相应单元格中。我想的是每个代码点的结束八位字节将映射到生成的Unicode字符,并且前导字节映射到随序列长度变化的占位符(可能是circled forms并使用颜色将它们与实际编码字符),以及与占位符类似的延续和无效字节。

struct UtfOctetVisualization
{
    enum Classification 
    { 
       Ascii, 
       NonAscii, 
       LeadByteOf2, 
       LeadByteOf3, 
       LeadByteOf4, 
       Continuation, 
       Error
    }

    Classification OctetClass;
    int CodePoint; // valid only when OctetClass == Ascii or NonAscii
}

Encoding.UTF8.GetString()方法并未提供有关每个结果字符来自的位置的任何信息。

我可以使用Encoding.UTF8.GetDecoder()并调用Convert一次传递一个字节,以便completed输出参数为每个八位字节提供分类。

但是在这两种方法中,为了处理无效字符,我需要实现一个DecoderFallback类?这看起来很复杂。

是否有一种简单的方法可以使用.NET提供的API(System.Text或其他方式)获取此信息?使用System.Text.Decoder,回退看起来会填充与解码器共享的输出数组?

或者编写自定义UTF-8识别器(有限状态机)更可行吗?

1 个答案:

答案 0 :(得分:1)

如何一次解码一个字符,以便捕获每个字符占用的字节数。像这样:

string data  = "hello????";

byte[] buffer = new byte[Encoding.UTF8.GetByteCount(data)];
int bufferIndex = 0;

for(int i = 0; i < data.Length; i++)
{
    int bytes = Encoding.UTF8.GetBytes(data, i, 1, buffer, bufferIndex);

    Console.WriteLine("Character: {0}, Position: {1}, Bytes: {2}", data[i], i, bytes);

    bufferIndex += bytes;
}

小提琴:https://dotnetfiddle.net/poohHM

那些???&#34;字符串中的字符串应该是多字节字符,但是请让我将它们粘贴进去。请参阅小提琴。

如果@Jon指出,当你将二进制内容与字符混合时,我就不会按照你想要的方式进行锻炼。我的意思是你会看到一些东西,但它可能不是你所期望的,因为编码器无法区分哪些字节应该是字符。