Как проверить наличие недопустимых символов UTF-8?
Теперь существует множество поддерживаемых шестнадцатеричных (UTF-8) сущностей, начиная с десятичных значений от 0 до 10175, есть ли быстрый способ проверки определенного значения, содержащегося в переменной, является одним из значений поддерживаемой шестнадцатеричной (UTF-8)) лица.
бывший
var something="some string value";
char[] validCharacter = new[] { All 10175 UTF-8 Hexadecimal characters };
if(validCharacter.Contains(something))
{ \\do something };
Как я могу сделать эту проверку самым быстрым способом?
2 ответа
Это должно вернуть то, что вы просили. Он будет проверять как отсутствие непарного суррогата high/low, так и отсутствие неопределенных кодовых точек ("определено" зависит от таблиц unicode, присутствующих в используемой вами версии.NET, и от версии операционной системы).
static bool IsLegalUnicode(string str)
{
for (int i = 0; i < str.Length; i++)
{
var uc = char.GetUnicodeCategory(str, i);
if (uc == UnicodeCategory.Surrogate)
{
// Unpaired surrogate, like ""[0] + "A" or ""[1] + "A"
return false;
}
else if (uc == UnicodeCategory.OtherNotAssigned)
{
// \uF000 or \U00030000
return false;
}
// Correct high-low surrogate, we must skip the low surrogate
// (it is correct because otherwise it would have been a
// UnicodeCategory.Surrogate)
if (char.IsHighSurrogate(str, i))
{
i++;
}
}
return true;
}
Обратите внимание, что Unicode находится в постоянном расширении. UTF-8 способен отображать все кодовые точки Unicode, даже те, которые не могут быть назначены в настоящее время.
Некоторые примеры:
var test1 = IsLegalUnicode("abcdeàèéìòù"); // true
var test2 = IsLegalUnicode("⭐ White Medium Star"); // true, Unicode 5.1
var test3 = IsLegalUnicode(" Beaming Face With Smiling Eyes"); // true, Unicode 6.0
var test4 = IsLegalUnicode(" Slightly Smiling Face"); // true, Unicode 7.0
var test5 = IsLegalUnicode(" Hugging Face"); // true, Unicode 8.0
var test6 = IsLegalUnicode(" Rolling on the Floor Laughing"); // false, Unicode 9.0 (2016)
var test7 = IsLegalUnicode(" Star-Struck"); // false, Unicode 10.0 (2017)
var test8 = IsLegalUnicode("\uFF00"); // false, undefined BMP UTF-16 unicode
var test9 = IsLegalUnicode(""[0] + "X"); // false, unpaired high surrogate pair
var test10 = IsLegalUnicode(""[1] + "X"); // false, unpaired low surrogate pair
Обратите внимание, что вы можете кодировать в UTF-8 даже правильно сформированные "неизвестные" кодовые точки Unicode, такие как Star-Struck
,
Результаты взяты с.NET 4.7.2 под Windows 10.
UTF8Encoding.GetString(byteArray) сгенерирует исключение ArgumentException, если обнаружение ошибок включено.
Источник: https://msdn.microsoft.com/en-us/library/kzb9f993(v=vs.110).aspx
Но если вы тестируете что-то, что уже является строкой - насколько я знаю - это почти всегда будет действительным UTF8. (см. ниже.) Насколько я знаю, все строки C# кодируются в UTF16, который является кодировкой для всех символов Unicode. UTF8 - это просто другая кодировка для того же набора. т.е. для всех символов Unicode.
(Это может исключить некоторые новые символы Unicode и т. Д. Но их также не будет в UTF16, так что здесь это не будет иметь значения.)
Как кто-то прокомментировал, могут быть "половины" символов UTF16, которые будут действительными строками, но не будут действительными значениями UTF8. Так что вы можете Encoding.Unicode.GetBytes()
а потом Encoding.UTF8.GetString()
проверять. Но это, вероятно, будет довольно редко.