Как игнорировать маркер порядка байтов UTF-8 в сравнении строк?
У меня возникла проблема сравнения строк в Unit Test в С# 4.0 с использованием Visual Studio 2010. Этот же пример теста работает правильно в Visual Studio 2008 (с С# 3.5).
Вот соответствующий фрагмент кода:
byte[] rawData = GetData();
string data = Encoding.UTF8.GetString(rawData);
Assert.AreEqual("Constant", data, false, CultureInfo.InvariantCulture);
При отладке этого теста строка data
отображается невооруженным глазом, чтобы содержать точно такую же строку, что и литерал. Когда я позвонил data.ToCharArray()
, я заметил, что первым байтом строки data
является значение 65279
, которое является маркером байтов UTF-8. Я не понимаю, почему Encoding.UTF8.GetString()
поддерживает этот байт.
Как мне получить Encoding.UTF8.GetString()
, чтобы не помещать маркер байтового байта в результирующую строку?
Обновление: Проблема заключалась в том, что GetData()
, который читает файл с диска, считывает данные из файла с помощью FileStream.readbytes()
. Я исправил это, используя StreamReader
и преобразовывая строку в байты с помощью Encoding.UTF8.GetBytes()
, что и должно было делать в первую очередь! Спасибо за помощь.
Ответы
Ответ 1
Ну, я предполагаю, потому что исходные двоичные данные включают спецификацию. Вы всегда можете удалить спецификацию самостоятельно после декодирования, если вы этого не хотите, но вы должны рассмотреть вопрос о том, должен ли массив байтов учитывать спецификацию.
EDIT: В качестве альтернативы вы можете использовать StreamReader
для выполнения декодирования. Здесь пример, показывающий тот же массив байтов, который преобразуется в два символа с использованием Encoding.GetString
или одного символа через StreamReader
:
using System;
using System.IO;
using System.Text;
class Test
{
static void Main()
{
byte[] withBom = { 0xef, 0xbb, 0xbf, 0x41 };
string viaEncoding = Encoding.UTF8.GetString(withBom);
Console.WriteLine(viaEncoding.Length);
string viaStreamReader;
using (StreamReader reader = new StreamReader
(new MemoryStream(withBom), Encoding.UTF8))
{
viaStreamReader = reader.ReadToEnd();
}
Console.WriteLine(viaStreamReader.Length);
}
}
Ответ 2
Существует несколько более эффективный способ сделать это, чем создавать StreamReader и MemoryStream:
1) Если вы знаете, что всегда существует спецификация
string viaEncoding = Encoding.UTF8.GetString(withBom, 3, withBom.Length - 3);
2) Если вы не знаете, проверьте:
string viaEncoding;
if (withBom.Length >= 3 && withBom[0] == 0xEF && withBom[1] == 0xBB && withBom[2] == 0xBF)
viaEncoding = Encoding.UTF8.GetString(withBom, 3, withBom.Length - 3);
else
viaEncoding = Encoding.UTF8.GetString(withBom);
Ответ 3
Я считаю, что дополнительный символ удаляется, если вы Trim() расшифрованная строка