嵌入式Json文件中的编码错误

时间:2016-02-19 11:22:54

标签: c# encoding

我遇到了一个问题而无法解决问题。

我有这段代码:

    public List<NavigationModul> LoadNavigation()
    {
        byte[] navBytes = NavigationResources.Navigation;
        var encoding = GetEncoding(navBytes);            
        string json = encoding.GetString(navBytes);
        List<NavigationModul> navigation = JsonConvert.DeserializeObject<List<NavigationModul>>(json);
        return navigation;
    }

    public static Encoding GetEncoding(byte [] textBytes)
    {
       if (textBytes[0] == 0x2b && textBytes[1] == 0x2f && textBytes[2] == 0x76) return Encoding.UTF7;
        if (textBytes[0] == 0xef && textBytes[1] == 0xbb && textBytes[2] == 0xbf) return Encoding.UTF8;
        if (textBytes[0] == 0xff && textBytes[1] == 0xfe) return Encoding.Unicode; //UTF-16LE
        if (textBytes[0] == 0xfe && textBytes[1] == 0xff) return Encoding.BigEndianUnicode; //UTF-16BE
        if (textBytes[0] == 0 && textBytes[1] == 0 && textBytes[2] == 0xfe && textBytes[3] == 0xff) return Encoding.UTF32;
        return Encoding.ASCII;
    }

目标是从ResourceFile加载嵌入式Json文件(NavigationResources.Navigation)。导航文件是嵌入式文件。我们只是在使用ResourceManager来避免使用Magic字符串。

在加载嵌入文件的字节并检查其编码后,我现在从文件中读取String并将其传递给JsonConverter.DeserializeObject函数。

但不幸的是,由于无效的Json,这失败了。长话短说:加载的json字符串仍然包含编码标识字节。我无法弄清楚如何摆脱它。

我还尝试在加载字符串之前将utf8 bytearray转换为默认编码,但这只会使编码字节成为可见字符。

我和同行交谈过,他们告诉我他们在阅读嵌入式批处理文件时遇到了同样的问题,导致批处理文件损坏。他们也不知道如何解决问题,但想出了批处理文件本身的解决方法(在批处理文件中添加一个空行以使其工作)

有关如何解决此问题的任何建议吗?

2 个答案:

答案 0 :(得分:1)

感谢Alex K.我有一个解决方案:

在调用Encoding.GetString之前屏蔽了标识字节。

这是我现在用来执行任务的功能:

    public static string GetStringFromEncodedBytes(byte[] bytes) {
        Encoding encoding = Encoding.Default;
        int skipBytes = 0;
        if (bytes[0] == 0x2b && bytes[1] == 0x2f && bytes[2] == 0x76) {
            encoding = Encoding.UTF7;
            skipBytes = 3;
        }
        if (bytes[0] == 0xef && bytes[1] == 0xbb && bytes[2] == 0xbf)
        {
            encoding = Encoding.UTF8;
            skipBytes = 3;
        }

        if (bytes[0] == 0xff && bytes[1] == 0xfe)
        {
            encoding = Encoding.Unicode;
            skipBytes = 2;
        }

        if (bytes[0] == 0xfe && bytes[1] == 0xff)
        {
            encoding = Encoding.BigEndianUnicode;
            skipBytes = 2;
        }
        if (bytes[0] == 0 && bytes[1] == 0 && bytes[2] == 0xfe && bytes[3] == 0xff)
        {
            encoding = Encoding.UTF32;
            skipBytes = 4;
        }

        return encoding.GetString(bytes.Skip(skipBytes).ToArray());

    }

答案 1 :(得分:0)

这是一种更简单的方法,在解码后删除BOM

// Your data is always in UTF-8 apparently, so just rely on that.
string text = Encoding.UTF8.GetString(data);
if (text.StartsWith("\ufeff"))
{
    text = text.Substring(1);
}

当然,这有复制字符串的缺点。

或者如果你想要跳过字节:

// Again, we're assuming UTF-8
int start = data.Length >= 3 && data[0] == 0xef &&
            data[1] == 0xbb && data[2] == 0xbf)
            ? 3 : 0;
string text = Encoding.UTF8.GetString(data, start, data.Length - start);

这样您就不需要使用SkipToArray,也可以避免进行任何无关的复制。