Как проверить наличие недопустимых символов 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() проверять. Но это, вероятно, будет довольно редко.

Другие вопросы по тегам