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

本文关键字:编码 错误 Json 文件 嵌入式 | 更新日期: 2023-09-27 18:35:31

我遇到了一个问题,无法完全理解它。

我有这个代码:

    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;
    }

目标是从资源文件加载嵌入式 Json 文件 (NavigationResources.Navigation)。导航文件是一个嵌入文件。我们只是在抖动资源管理器以避免魔术字符串。

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

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

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

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

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

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

感谢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());
    }

这是一种更简单的方法,在解码删除 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 ,并且避免了进行任何无关的复制。