I've baca posting yang sama tentang hal ini dan mereka don't menjawab pertanyaan saya.
Dalam C#, aku punya string yang saya'm memperoleh dari WebClient.DownloadString. I've mencoba setting klien.Pengkodean baru UTF8Encoding(palsu), tapi yang's tidak membuat perbedaan - aku masih berakhir dengan sebuah byte order mark untuk UTF-8 pada awal hasilnya string. Aku harus menghapus ini (untuk mengurai dihasilkan XML dengan LINQ), dan ingin melakukannya di memori.
Jadi aku punya string yang dimulai dengan \x00EF\x00BB\x00BF, dan saya ingin menghapus itu jika ada. Sekarang saya'm menggunakan
if (xml.StartsWith(ByteOrderMarkUtf8))
{
xml = xml.Remove(0, ByteOrderMarkUtf8.Length);
}
tapi itu hanya terasa salah. I've mencoba segala macam kode dengan sungai, GetBytes, dan pengkodean, dan tidak ada yang berhasil. Siapa pun dapat memberikan "benar" algoritma untuk melucuti BOM dari sebuah string?
Terima kasih!
Saya baru-baru memiliki masalah dengan .net 4 upgrade tapi sampai kemudian jawaban yang sederhana adalah
String.Trim()
menghilangkan BOM sampai .net 3.5 Namun di .net 4 anda perlu mengubah sedikit
String.Trim(new char[]{'\uFEFF'});
Yang juga akan menyingkirkan Byte order mark, meskipun anda mungkin juga ingin menghapus NOL LEBAR RUANG U+200B
String.Trim(new char[]{'\uFEFF','\u200B'});
Ini bisa juga kamu gunakan untuk menghapus yang tidak diinginkan lainnya karakter
Beberapa informasi lebih lanjut dari http://msdn.microsoft.com/en-us/library/t97s7bs3.aspx
Yang .NET Framework 3.5 SP1 dan versi sebelumnya mempertahankan internal daftar karakter white-space bahwa metode ini trims. Mulai dengan .NET Framework 4, metode trims semua Unicode karakter white-space (yaitu, karakter yang menghasilkan mengembalikan nilai true ketika mereka berlalu untuk Char.IsWhiteSpace metode). Karena perubahan ini, Trim metode dalam .NET Framework 3.5 SP1 dan versi sebelumnya menghilangkan dua karakter, NOL LEBAR RUANG (U+200B) dan LEBAR NOL TIDAK ada ISTIRAHAT RUANG (U+FEFF), yang Memangkas metode dalam .NET Framework 4 dan versi yang lebih baru tidak menghapus. Selain itu, Memangkas metode dalam .NET Framework 3.5 SP1 dan versi sebelumnya tidak memangkas tiga Unicode karakter white-space: MONGOLIA VOKAL PEMISAH (U+180E), SEMPIT TIDAK ada ISTIRAHAT RUANG (U+202F), dan MEDIA MATEMATIKA RUANG (U+205F).
Aku punya beberapa tes yang salah data, yang menyebabkan beberapa kebingungan. Berdasarkan Bagaimana untuk menghindari tersandung BOM UTF-8 ketika membaca file saya menemukan bahwa ini bekerja:
private readonly string _byteOrderMarkUtf8 =
Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
public string GetXmlResponse(Uri resource)
{
string xml;
using (var client = new WebClient())
{
client.Encoding = Encoding.UTF8;
xml = client.DownloadString(resource);
}
if (xml.StartsWith(_byteOrderMarkUtf8, StringComparison.Ordinal))
{
xml = xml.Remove(0, _byteOrderMarkUtf8.Length);
}
return xml;
}
Pengaturan klien Encoding properti dengan benar mengurangi BOM ke sebuah karakter tunggal. Namun, XDocument.Mengurai masih tidak akan membaca string tersebut. Ini adalah terbersih versi I've datang dengan to date.
Jika variabel xml adalah tipe string, anda melakukan sesuatu yang salah yang sudah dalam karakter string, BOM tidak harus diwakili sebagai tiga karakter yang terpisah, tetapi sebagai satu kode titik. Alih-alih menggunakan DownloadString, gunakan DownloadData, dan mengurai byte array sebagai gantinya. XML parser harus mengakui BOM itu sendiri, dan melewatkan itu (kecuali untuk auto-mendeteksi pengkodean dokumen sebagai UTF-8).
Sebuah metode cepat dan sederhana untuk menghapusnya langsung dari string:
private static string RemoveBom(string p)
{
string BOMMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
if (p.StartsWith(BOMMarkUtf8))
p = p.Remove(0, BOMMarkUtf8.Length);
return p.Replace("\0", "");
}
Bagaimana untuk menggunakan:
string yourCleanString=RemoveBom(yourBOMString);
Aku punya masalah yang sama (yang saya butuhkan untuk mengurai XML dokumen direpresentasikan sebagai sebuah byte array yang memiliki byte order mark di awal). Saya menggunakan salah satu dari Martin's komentar pada jawaban-nya untuk datang ke sebuah solusi. Aku mengambil byte array yang saya punya (bukan konversi ke string) dan menciptakan sebuah MemoryStream
objek dengan itu. Kemudian aku berlalu ke XDocument.Beban
, yang bekerja seperti pesona. Misalnya, let's mengatakan bahwa xmlBytes
berisi XML anda dalam encoding UTF8 dengan byte mark di awal itu. Maka, ini akan menjadi kode untuk memecahkan masalah:
var stream = new MemoryStream(xmlBytes);
var document = XDocument.Load(stream);
It's yang sederhana.
Jika dimulai dengan string, itu masih harus mudah untuk dilakukan (misalnya xml
adalah string yang berisi XML dengan byte order mark):
var bytes = Encoding.UTF8.GetBytes(xml);
var stream = new MemoryStream(bytes);
var document = XDocument.Load(stream);
Saya menulis pasca setelah datang di masalah ini.
Pada dasarnya bukan membaca dalam baku byte dari file's isi menggunakan BinaryReader kelas, saya menggunakan StreamReader kelas tertentu dengan konstruktor yang secara otomatis menghapus byte order mark karakter dari data tekstual saya mencoba untuk mengambil.
Lulus byte buffer (via DownloadData) untuk string Encoding.UTF8.GetString(byte[])
untuk mendapatkan string daripada download buffer string. Anda mungkin memiliki lebih banyak masalah dengan anda saat ini metode dari pemangkasan byte order mark. Kecuali anda're benar decoding itu seperti yang saya sarankan di sini, karakter unicode mungkin akan disalahartikan, sehingga rusak string.
Edit: Martin's jawaban yang lebih baik, karena menghindari mengalokasikan seluruh string XML yang masih perlu diuraikan pula. Jawaban yang saya berikan terbaik berlaku untuk umum string yang don't perlu diurai sebagai XML.
Aku berlari ke ini ketika saya punya base-64 file yang dikodekan untuk berubah menjadi string. Sementara saya bisa telah disimpan ke file dan kemudian membacanya dengan benar, di sini's solusi terbaik yang saya bisa memikirkan untuk mendapatkan dari `byte [] dari file ke string (Berdasarkan ringan di TrueWill's jawaban):
public static string GetUTF8String(byte[] data)
{
byte[] utf8Preamble = Encoding.UTF8.GetPreamble();
if (data.StartsWith(utf8Preamble))
{
return Encoding.UTF8.GetString(data, utf8Preamble.Length, data.Length - utf8Preamble.Length);
}
else
{
return Encoding.UTF8.GetString(data);
}
}
Di mana StartsWith(byte[])
adalah perpanjangan logis:
public static bool StartsWith(this byte[] thisArray, byte[] otherArray)
{
// Handle invalid/unexpected input
// (nulls, thisArray.Length < otherArray.Length, etc.)
for (int i = 0; i < otherArray.Length; ++i)
{
if (thisArray[i] != otherArray[i])
{
return false;
}
}
return true;
}
It's tentu saja yang terbaik jika anda dapat strip itu selagi masih pada byte array tingkat untuk menghindari hal yang tidak diinginkan substring / allocs. Tapi jika anda sudah memiliki sebuah string, ini mungkin cara termudah dan paling performant cara untuk menangani hal ini.
Penggunaan:
string feed = ""; // input
bool hadBOM = FixBOMIfNeeded(ref feed);
var xElem = XElement.Parse(feed); // now does not fail
/// <summary>
/// You can get this or test it originally with: Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble())[0];
/// But no need, this way we have a constant. As these three bytes `[239, 187, 191]` (a BOM) evaluate to a single C# char.
/// </summary>
public const char BOMChar = (char)65279;
public static bool FixBOMIfNeeded(ref string str)
{
if (string.IsNullOrEmpty(str))
return false;
bool hasBom = str[0] == BOMChar;
if (hasBom)
str = str.Substring(1);
return hasBom;
}
Namun lain generic variasi untuk menyingkirkan BOM UTF-8 pembukaan:
var preamble = Encoding.UTF8.GetPreamble();
if (!functionBytes.Take(preamble.Length).SequenceEqual(preamble))
preamble = Array.Empty<Byte>();
return Encoding.UTF8.GetString(functionBytes, preamble.Length, functionBytes.Length - preamble.Length);