如何从字节数组中删除BOM

时间:2013-03-18 11:49:44

标签: c# .net byte-order-mark

我在xml中有byte[] byteArray个数据,可能包含也可能不包含BOM。 C#中是否有任何标准方法可以从中删除BOM?如果没有,那么处理包括所有类型编码在内的所有情况的最佳方法是什么呢?

实际上,我正在修复代码中的错误,我不想更改大部分代码。所以如果有人能给我删除BOM的代码会更好。

我知道我可以找到60,其中ASCII值为'<'并在此之前忽略字节但我不想这样做。

5 个答案:

答案 0 :(得分:6)

所有C#XML解析器都会自动为您处理BOM。我建议使用XDocument - 在我看来,它提供了最清晰的XML数据抽象。

以XDocument为例:

using (var stream = new memoryStream(bytes))
{
  var document = XDocument.Load(stream);
  ...
}

一旦有了XDocument,就可以使用它来省略没有BOM的字节:

using (var stream = new MemoryStream())
using (var writer = XmlWriter.Create(stream))
{
  writer.Settings.Encoding = new UTF8Encoding(false);
  document.WriteTo(writer);
  var bytesWithoutBOM = stream.ToArray();
}

答案 1 :(得分:0)

您必须在字节数组的开头标识字节顺序标记。有几种不同的组合,如http://www.unicode.org/faq/utf_bom.html#bom1所述。

只需创建一个从字节数组开头开始的小型状态机,然后查找这些序列。

我不知道你的阵列是如何使用的,或者你使用的是什么其他参数,所以我不能说你如何“删除”序列。您的选项似乎是:

  1. 如果您有startcount参数,则可以更改这些参数以反映数组的起点(超出BOM)。
  2. 如果您只有count参数(数组的Length属性除外),则可以移动数组中的数据以覆盖BOM,并相应地调整count。 / LI>
  3. 如果您没有startcount参数,那么您将需要创建一个新数组,该数组的大小与旧数组相比减去BOM,并将数据复制到新数组中阵列。
  4. 要“删除”序列,您可能需要识别标记,如果它在那里,然后将剩余的字节复制到新的字节数组。或者,如果您保留字符数(除了数组的Length属性)

答案 2 :(得分:0)

您可以执行类似这样的操作,以便在从流中读取时跳过BOM字节。你需要扩展Bom.cs以包含进一步的编码,但是afaik UTF是唯一使用BOM的编码...虽然可能(很可能)是错误的。

我从here

获得了有关编码类型的信息
using (var stream = File.OpenRead("path_to_file"))
{
    stream.Position = Bom.GetCursor(stream);
}


public static class Bom
{
        public static int GetCursor(Stream stream)
        {
            // UTF-32, big-endian
            if (IsMatch(stream, new byte[] {0x00, 0x00, 0xFE, 0xFF}))
                return 4;
            // UTF-32, little-endian
            if (IsMatch(stream, new byte[] { 0xFF, 0xFE, 0x00, 0x00 }))
                return 4;
            // UTF-16, big-endian
            if (IsMatch(stream, new byte[] { 0xFE, 0xFF }))
                return 2;
            // UTF-16, little-endian
            if (IsMatch(stream, new byte[] { 0xFF, 0xFE }))
                return 2;
            // UTF-8
            if (IsMatch(stream, new byte[] { 0xEF, 0xBB, 0xBF }))
                return 3;
            return 0;
        }

        private static bool IsMatch(Stream stream, byte[] match)
        {
            stream.Position = 0;
            var buffer = new byte[match.Length];
            stream.Read(buffer, 0, buffer.Length);
            return !buffer.Where((t, i) => t != match[i]).Any();
        }
    }

答案 3 :(得分:0)

您不必担心BOM表。

如果出于某些原因需要使用XmlDocument对象,则此代码可以为您提供帮助:

SELECT logs.*
FROM logs
CROSS APPLY OPENJSON([log], '$.tags') WITH (id INT '$.id')
WHERE id = 13

当我尝试使用Google Api从gmail帐户下载xml附件并且文件具有BOM并使用Encoding.UTF8.GetString(file_content)不能“正常”工作时,它对我有用。

答案 4 :(得分:0)

您还可以使用 StreamReader。

假设您有一个 MemoryStream ms

    using (StreamReader sr = new StreamReader(new MemoryStream(ms.ToArray()), Encoding.UTF8))
    {
         var bytesWithoutBOM = new UTF8Encoding(false).GetBytes(sr.ReadToEnd());
         var stringWithoutBOM = Convert.ToBase64String(bytesWithoutBOM );
    }