2013-03-18 84 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(); 
     } 
    } 
相關問題