2013-03-18 162 views
4

除去BOM我在byte[] byteArrayxml数据可以或那下跪包含BOM。 C#中有没有标准的方法来删除它的BOM?如果不是,那么处理包括所有类型编码在内的所有情况的最好方法是什么?如何从字节数组

其实,我在固定的代码中的错误,我不希望改变很多代码。所以如果有人可以给我代码删除BOM会更好。

我知道我可以像找出60这是'<'的ASCII值并忽略字节,但我不想这样做。

+0

数据既可以是UTF-8(具有或不具有字节顺序标记)或UTF16(有或全无BOM;小端或大端)? – 2013-03-18 12:04:39

+0

我编辑了你的标题。请参阅:“[应该在其标题中包含”标签“吗?](http:// meta。stackexchange.com/questions/19190/)“,其中的共识是”不,他们不应该“。 – 2013-03-18 13:07:08

回答

5

所有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(); 
} 
+0

实际上我只想删除BOM,不必关心解析和所有。我也更新了这个问题 – 2013-03-18 12:39:03

+0

@RaviGupta我看,你知道编码吗? – 2013-03-18 12:42:53

+0

这将是更好的,如果逻辑编码自由。 – 2013-03-18 12:46:50

0

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

只需创建始于字节数组的开头和查找这些序列的小状态机。

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

  1. 如果你有startcount参数,你可以改变这些以反映阵列的起点(超出BOM)。
  2. 如果您只有count参数(数组的Length属性除外),则可以移动数组中的数据以覆盖BOM,并相应地调整count
  3. 如果您没有startcount参数,那么您需要创建一个与旧数组大小相同的新数组减去BOM,然后将数据复制到新数组中。

要“移除”序列,您可能需要标识标记(如果存在),然后将其余字节复制到新的字节数组中。或者,如果你保持字符数(大于数组的Length财产等)

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(); 
     } 
    } 
相关问题