如何从字节数组中删除BOM
本文关键字:删除 BOM 数组 字节数 字节 | 更新日期: 2023-09-27 18:04:22
我在byte[] byteArray
中有xml
数据,可能包含也可能不包含BOM。在c#中有什么标准的方法来删除BOM吗?如果不是,最好的方法是什么,它处理所有的情况,包括所有类型的编码,做同样的?
实际上,我正在修复代码中的一个错误,我不想更改太多代码。所以如果有人能给我代码来删除BOM就更好了。
我知道我可以找到60
它是'<'的ASCII值并忽略之前的字节但我不想这样做
所有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();
}
您不必担心BOM。
如果出于某种原因你需要使用XmlDocument对象,也许这段代码可以帮助你:
byte[] file_content = {wherever you get it};
XmlDocument xml = new XmlDocument();
xml.Load(new MemoryStream(file_content));
它为我工作时,我试图下载xml附件从gmail帐户使用谷歌Api和文件有BOM和使用Encoding.UTF8.GetString(file_content)没有工作"正常"。
您可以这样做,以便在从流读取时跳过BOM字节。您需要扩展BOM. cs以包含更多的编码,但是恐怕UTF是使用BOM的唯一编码…但我很可能错了。
我从这里得到了编码类型的信息
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();
}
}
你也可以使用StreamReader。
假设你有一个内存流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 );
}
您必须在字节数组的开始处识别字节顺序标记。有几种不同的组合,如http://www.unicode.org/faq/utf_bom.html#bom1所述。
创建一个小状态机,从字节数组的开头开始查找这些序列。
我不知道你的数组是如何使用的,也不知道你使用的其他参数是什么,所以我不能真正说你是如何"删除"序列的。您的选项似乎是:
- 如果你有
start
和count
参数,你可以改变那些反映数组的起点(超出BOM)。 - 如果你只有一个
count
参数(而不是数组的Length
属性),你可以移动数组中的数据来覆盖BOM,并相应地调整count
。 - 如果你没有
start
或count
参数,那么你需要创建一个新的数组,这是旧数组减去BOM的大小,并复制数据到新的数组。
要"删除"序列,您可能需要识别标记,如果它在那里,然后将剩余的字节复制到一个新的字节数组。或者,如果您维护一个字符计数(除了数组的Length
属性)