2012-04-23 8 views
3

Я столкнулся с очень странной проблемой, в которой у меня есть байт [], и когда я передаю этот метод Convert.UTF8.GetString (byte []), системная кодировка возиться с моими байтами и заменять лишь несколько специальных байтов (которые я использую как маркеры в моей системе) на три строковых представления символов.C# Encoding.UTF8 испортить байты []

[0] 70 byte 
[1] 49 byte 
[2] 45 byte 
[3] 86 byte 
[4] 49 byte 
[5] 253 byte  <-- Special byte 
[6] 70 byte 
[7] 49 byte 
[8] 45 byte 
[9] 86 byte 
[10]50 byte 
[11]253 byte  <-- Special byte 
[12]70 byte 
[13]49 byte 
[14]45 byte 
[15]86 byte 
[16]51 byte 

Когда я проходя выше байт [] в Encoding.UTF8.GetString (байт) Метод Я получаю следующие выходные;

private Encoding _encoding = System.Text.Encoding.GetEncoding("UTF-8", new EncoderReplacementFallback("?"), new DecoderReplacementFallback("?"));  
_encoding.GetString(bytes) "F1-V1�F1-V2�F1-V3" string 

Фактическое значение не должно быть «», так как это означает, что он не смог закодировать и заменить эти специальные байты с «». В любом случае, я могу обойти это, например, преобразовать в строку и сохранить специальное представление байтов в один символ.

У меня есть следующие специальные байты, которые я пытаюсь использовать в качестве маркеров;

byte AM = (byte) 254 
byte VM = (byte) 253 
byte SM = (byte) 252 

Ваша помощь и комментарии будут оценены.

Спасибо,

-

Sheeraz

ответ

2

данные только UTF-8 между маркерами, так что, если бы это было я бы извлекая разграниченные части первого, а затем в UTF-8 декодировать каждую порцию отдельно, т.е. прочитать byte[] ищет маркеры в ваших двоичных данных, что дает вам 3 бинарных куска (70,49,45,86,49; 70,49,45,86,50; 70,59,45,86,51), которые затем декодируются в 3 строки. Вы не можете UTF-8 декодировать всю двоичную последовательность, так как недействителен UTF-8.

Однако лично я бы сказал, что использование разделителя здесь опасно; Я бы, вероятно, пойти на длину префикса подхода, так что

  • Я знаю, что я не случайно приравнивая разделители и реальные данные
  • я могу обрабатывать его более эффективно, чем байт за байтом

Например, если мы использовали «varint» префикс длины, который был бы:

05,70,49,45,86,49,05,70,49,45,86,50,05,70,59,45,86,51 

где 05 является «varint» длина которой мы интерпретируем как 5 байт; это означает, что мы можем обработать красиво:

// pseude code 
while(!EOF) { 
    int len = ReadVarint(); 
    var blob = ReadBytes(len); 
    string s = Utf8Decode(blob); 
    // ... 
} 
+0

Спасибо ... Я должен сделать это вручную, потому что требование состоит в том, чтобы все в кодировке UTF-8, поскольку моя БД - только UTF-8. Я теперь не преобразовываю ничего в String, но только для байтов. – SJunejo

+0

@SJunejo k, но обратите внимание: ваша текущая стратегия ** не UTF-8 **. Ваша база данных будет полностью в пределах своих прав на взрыв в вас. –

7

Вы не можете использовать эти специальные значения в качестве маркеров внутри строки в UTF-8, потому что строка заканчивается время недействительна в соответствии с UTF-8 encoding rules ,

Вы мог скрытно вставить их, а затем принять их обратно до того данные подаются в UTF-8 осведомленные коды, как Encoding.GetString, но это не очень хорошая идея, именно потому, что это подлое (способа запутанного любой, кто еще не знает, что происходит в вуду, и таким образом очень контрпродуктивный).

Более разумным вариантом было бы просто вставить «специальные» кодированные символы UTF-8 внутри вашей строки. Это было бы технически необходимо (особенно если вы выберете символ, который кодирует до 1 байта, так как они будут чаще встречаться внутри вашей реальной полезной нагрузки), что вы также придумаете схему escape этих символов, когда они происходят естественным образом внутри ваша полезная нагрузка.

+0

+1 Если вам нужны такие маркеры, вы можете выбрать символ где-нибудь внутри Юникода, чтобы использовать вместо него, например. в одном из частных диапазонов, а затем использовать допустимые кодировки UTF-8 этих символов в качестве маркеров. Но они будут более одного байта каждый. Или порежьте поток байтов вокруг ваших маркеров досрочно, а затем преобразуйте каждый допустимый раздел в Unicode за раз, но вам нужно быть осторожным, чтобы на самом деле не подбирать подлинные кодировки UTF-8, используя эти байты - то есть эффективно писать собственный декодер. – Rup

Смежные вопросы