2016-08-02 5 views
4

Я хотел бы удалить 4 байта UTF8 символов, которая начинается с \ xF0 (полукокса с кодом ASCII 0xF0) из строки и попыталсяОткрутить 4 байт UTF8 символов

sText = Regex.Replace (sText, "\xF0...", ""); 

Это не работает. Использование двух обратных косых черт не получилось.

Точный вход содержание https://de.wikipedia.org/w/index.php?title=Spezial:Exportieren&action=submit&pages=Unicode 4 байта символов ист одного после текста "[[Violinschlüssel]]", в шестнадцатеричном виде: .. 0x65 0x6c 0x5d 0x5d 0x20 0xf0 0x9d 0x84 0x20 0x9e .. Ожидаемый выход 0x65 0x6c 0x5d 0x5d 0x20 0x20 ..

Что случилось?

+0

Используйте две обратной косой черты. – jdweng

+1

Возможно, потому, что вы попытались удалить символ '' ð' '(https://ideone.com/YizDeh). Каков ваш точный ввод и точный ожидаемый результат? –

+1

Комментарии для _us_, чтобы спросить _you_ для уточнения. Поставьте свои разъяснения в самом вопросе, нажав ссылку [edit] (https://stackoverflow.com/posts/38714663/edit) и обновив сообщение. –

ответ

5

Такие символы будут суррогатных пар в .NET, который использует UTF-16. Каждый из них будет два блока UTF-16, то есть два значения char.

Чтобы просто удалить их, вы можете сделать (using System.Linq;):

sText = string.Concat(sText.Where(x => !char.IsSurrogate(x))); 

(использует перегрузку Concat введенную в .NET 4.0 (Visual Studio 2010)).


Late дополнение: Это может дать более высокую производительность для использования:

sText = new string(sText.Where(x => !char.IsSurrogate(x)).ToArray()); 

даже если она выглядит хуже. (Работает в .NET 3.5 (Visual Studio 2008).)

+0

Это работает. Большое спасибо. –

+0

Насколько я понимаю, удаляются все 3 и 4 байтовые символы UTF8 (которые содержат 2 значения символов UTF16 в строках C#). Это не совсем то, что я просил, но я узнал, что это именно то, что я действительно требую. Еще раз спасибо. –

+0

@ Андре Вы ошибаетесь. Если вы хотите удалить символы, соответствующие 3 байтам UTF-8 или дольше, просто используйте 'sText = string.Concat (sText.Where (x => x <'\ u0800'));'. UTF-8 может использоваться в файлах, но он не используется .NET или Windows после того, как 'string' находится в памяти. Если персонажу требуется 1, 2 или 3 байта в UTF-8, он может поместиться в один единственный_код unit_ (то есть одно единственное значение «char») в UTF-16, которое является кодировкой, используемой внутри .NET и Windows. Если символу требуется 4 байта в UTF-8, ему нужны два UTF-16 _code units_ (так _two_ 'char'); эти два составляют «суррогатную пару». –

2

Вы пытаетесь найти значения byte, но строки C# сделаны из char значений. Спецификация языка C# в разделе «2.4.4.4 Символьные литералы»:

Литеральный символ представляет собой один символ и обычно состоит из символа в кавычках, как в 'a'.
...
Шестнадцатеричная escape-последовательность представляет одиночный символ Unicode со значением, образованным шестнадцатеричным числом, следующим за \x.

Поэтому поиск "\xF0..." ищет характер U+F0, который будет представлен в байтах C3 B0.

Если вы хотите найти замену всех символов Юникода, первый байт которого равен 0xF0, тогда я считаю, что вам нужно искать значения символов, первый байт которых равен 0xFO.

Персонаж U+10000 представлен как F0 90 80 80 (предыдущий код U+FFFF который является EF BF BF). Первый код с F1 .... .. равен U+40000, который равен F1 80 80 80, а значение составляет U+3FFFF, которое составляет F0 BF BF BF.

Следовательно, вам необходимо удалить символы в диапазоне U+10000 до U+3FFFF. Это должно быть возможным с помощью регулярного выражения, таких как

sText = Regex.Replace (sText, "[\\x10000-\\x3FFFF]", ""); 

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

static void Main(string[] args) 
{ 
    string input = "] ("; 
    Console.Write("Input length {0} : '{1}' : ", input.Length, input); 
    foreach (char cc in input) 
    { 
     Console.Write(" {0,2:X02}", (int)cc); 
    } 
    Console.WriteLine(); 
} 

Выходные данные программы приведены ниже. Это поддерживает суррогатную пару объяснение @Jeppe в его ответе.

Input length 6 : '] ?? (' : 5D 20 D834 DD1E 20 28 
+0

@Qix Почему вы хотите изменить прямая цитата из языкового стандарта? В цитируемом разделе нет жирного текста, а в его использовании используются строковые кавычки. Пожалуйста, объясни. – AdrianHHH

+1

Потому что это лучше подчеркивает вашу точку зрения. Это не меняет смысл спецификации. Мне пришлось искать причину, по которой вы включали обозначение одного символа и должны были искать ответ _real_, что является различием между символом unicode и единственным байтом. – Qix

+0

@Qix Первое предложение моего ответа относится к разнице между 'char' и' byte' в C. – AdrianHHH

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