嵌入式 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 字节数组转换为默认编码,但这只会使编码字节成为可见字符。
我和我的同行交谈过,他们告诉我,他们在读取嵌入式批处理文件时遇到了同样的问题,导致批处理文件损坏。他们也不知道如何解决问题,但为批处理文件本身提出了解决方法(在批处理文件中添加一个空行以使其工作)
关于如何解决此问题的任何建议?
感谢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);
这样你就不需要使用 Skip
和 ToArray
,并且避免了进行任何无关的复制。