предисловие
Я также поделился большим опытом наступания на ямы в своей работе:
- Думая об онлайн-проблеме: как кластер реестра Eureka обеспечивает загрузку клиентских запросов и аварийное переключение?
- [Оригинал] Обмен опытом: кровавый случай, вызванный длиной содержания (почти ....)
Сегодня поделюсь реальным случаем на работе:
На странице списка оценки продукта отображаются сведения об оценке каждого пользователя.В целях защиты конфиденциальности пользователей требуется отображать только первую и последнюю цифры псевдонима пользователя, а остальные заменять на *.
Например, ввод: 🐳🐳🐠, вывод: 🐳***🐠
Это кажется пресным требованием, и мне все равно. Сервер хранит информацию о комментариях пользователя вdb
, интерфейс списка обзоров предназначен для отображения обзорной информации о продукте в базе данных, а псевдоним рецензента достаточен при особой обработке.
но! !Тестовые одноклассники обнаружили, что никнейм пользователя содержитemoji表情
При возникновении проблемы данные резки будутЗнак вопроса показывает! !
Пример кода для моделирования выглядит следующим образом:
вывод:
Увидев этот результат, я действительно сбит с толку, это совсем не тот результат, которого я хочу! ! !
Эти три рыбы можно считать преткновением для меня, можно ли только сказать на тестсмайлики слишком особенныене обрабатывать? потомкокетливыйПерепутать?
Долго думая об этом, я все же решил столкнуться с этой проблемой и решить ее!(Ведь я еще тот маленький умный призрак, который не боится трудностей 🤔)
PS: Эта статья во многом навеяна тем, что коллега по компании поделился юникодом. Здесь я отдаю должное моему учителю! В следующем содержании будет поэтапно проанализировано создание этой проблемы и окончательное решение.
Концептуальные знания
Чтобы решить эти проблемы, вы должны заложить некоторые базовые знания. Вам не терпится увидеть решение. Вы можете использовать пример кода в конце статьи.
utf8mb4
Как правило, мы используем этот формат кодировки по умолчанию при создании таблиц в базе данных:
Я думаю, что все знакомы с этим форматом кодирования, когда мы хотим сохранитьemoji
данные в базу данных, то формат базы данных должен быть указан какutf8mb4
В противном случае хранилище сообщит об ошибке. Так во многих компанияхdb规范
, кодировка базы данных по умолчанию должна бытьutf8mb4
Но вы когда-нибудь задумывались, почему?utf8
ни за чтоutf8mb4
Просто сделай это? что здесьизогнутая дорога?
Это включает в себяunicode
Актуальные знания, о которых мы упомянем ниже, все будут продолжать читать.
существуетmysql 5.5
До,utf8
поддерживается только кодировка1-3
байт, изmysql 5.5
Старт, может поддерживать 4 байтаUTF
кодированиеutf8mb4
Персонаж может иметь больше всего4 байта, поэтому он может поддерживать больше наборов символов.
Эта таблица содержит всеemoji
и соответствующийunicode
код, но и соответствующийutf-8
Реализация кодировки.
Это также можно увидеть с фигурыemoji
для выражений лицаutf-8
Занимать при выражении4 байта, поэтому база данных используетutf8
не может быть сохраненemoji
Причина выражения.
Точно так же мы можем такжеjava
посмотри в кодеemoji
Занимает несколько байт в длину:
мы также можем видетьString.getBytes()
, по умолчаниюutf-8
Закодировано:
ASCII-код
Представлено вышеutf8mb4
упоминается время от времениunicode
, прежде чем представить его, мы также должны упомянуть нашего старого друга:ASCII
код
ASCII (Американский стандартный код для обмена информацией) — это компьютерная система кодирования, основанная на латинском алфавите. Он в основном используется для отображения современного английского языка.
Таким образом, мы можем использовать один байт для представления современного английского языка, который выглядит очень хорошо Соответствие между некоторыми данными следующее:
Но это может отображаться только для представления латиницы, чего явно недостаточно.
Unicode
Очевидно, что развитие компьютеров поддерживает не только английский как язык,ASCII
Ограничение состоит в том, что он может отображать только26个
Базовый латинский алфавит, арабские цифры и британская пунктуация, поэтому его можно использовать только для отображения современного американского варианта английского языка.
Тогда, если есть набор символов, который содержит все текст в мире, в каждом регионе текста в этом наборе символов есть уникальное двоичное представление, так что не будет искажена проблемой. такUnicode
Оно тоже возникло.
концепция
Юникод, также известный как Универсальный код, Международный код, Юникод и Единый код на китайском языке, является отраслевым стандартом в области компьютерных наук. Он упорядочивает и кодирует большинство систем письма в мире, облегчая компьютерам представление и обработку слов.
плоский
Unicode
Первый, кто призналASCII
Занять0-127Легитимность целочисленных ресурсов после повторного использования128-65535
Имея так много целочисленных ресурсов, мы можем присвоить целое число каждому символу различных языков мира.
после,Unicode
Открытие Альянса65536Количество целых чисел недостаточно для выделения, поэтому мы просто присваиваем следующие по одному.16 65536число65536-1114111Заняты целые ресурсы, а затем более занятые16 65536Сегменты называются16 самолетов, плюс оригинал0-65535 Квартира,Unicode
Всего17 самолетов.比如第 1 平面就是65536-131072. Конечно, пока только7 самолетоввыйти.
Самолет 0,ДаUnicode
中的一个编码区段。 кодирование изU+0000
кU+FFFF
, символы этого плана мы используем чаще всего.
65535Персонажи, назначенные после этого, в основномemoji
Выражения типа 😺 Да128570 (\uD83D\uDE3A)
Вот рекомендуемый онлайн-сайт для преобразования кода:Длинные волосы, это тоже больно.com/C encode.htm…
Это представляет диапазон
Unicode
Диапазон представления:U+0000 ~ U+10FFFF
- Это примерно: U+0000~U+110000 (плюс 1), что составляет 17 FFFF (65535)
- Почти 17 * 6w, есть около 100 кодовых точек, которые можно использовать для сопоставления символов.
- Точное значение — 1114 112, что составляет почти 112 кодовых точек.
- Последняя версия Unicode содержит 136 690 символов, что далеко не 100 Вт.
- Unicode официально заявил, что текущие кодовые точки достаточны и не будут расширяться в будущем.
Метод реализации
Unicode
реализуется иначе, чем кодирование. один персонажUnicode
Кодирование является детерминированным. Однако в реальном процессе передачи, поскольку конструкции различных системных платформ не обязательно согласованы, и в целях экономии места,Unicode
Кодировка реализована по-разному.Unicode
реализация называетсяUnicode
Формат преобразования (формат преобразования Unicode, называемый UTF).
за то, чтоUnicode
收录的字符其编码是唯一且确定的。 ноUnicode
реализации (для транспортировки, хранения, обработки или обратной совместимости) различаются по нескольким параметрам, наиболее популярными из которых являютсяUTF-8
,UTF-16
,UCS2
,UCS4/UTF-32
подождите, есть подразделенияРазмерразница.
о насJava
, отchar
Занять2 байтасделать вывод, что с помощьюUTF-16
код для хранения
Хорошая статья рекомендуется для различных проблем с кодированием:Углубленный анализ проблем китайской кодировки в Java
Определите, следует ли включать китайский язык
Наверное понял вышеUnicode
значение и использованиеИтак, каков практический эффект от знания этого материала?
Давайте рассмотрим небольшое требование, например:Как определить, что строка содержит китайский язык?
Я думаю, что все сталкивались с таким спросом.Вообщем, мы пойдем на Baidu Yitong, и мы должны быть в состоянии найти регулярное выражение, чтобы судить, содержит ли оно китайский язык, а затем решить проблему с радостью.
Так уж получилось, что в нашей системе есть такое штатное суждение, которое инкапсулируется коллегами из группы архитектуры, давайте посмотрим на него вместе:
Очевидно, здесь черезUnicode
Есть ли проблема в оценке интервала?
Интервал здесь используетсяЕдиные иероглифы Китая, Японии и Кореи, но это версия 1993 года, которая содержит большую часть нашего общеупотребительного китайского языка, в общей сложности20902После просмотра дополненной версии было добавлено много слов, поэтому вполне возможно, что метод суждения, который мы используем сейчас, определенно пропустит слова, добавленные позже:
Используем прибавку 2000 г.Зона расширения единой иероглифы Китай-Япония-Корея AДавайте проверим это на примере:
Здесь добавлено много неупотребительных слов, а я их даже не знаю.Давайте воспользуемся данными во второй строке для проверки:
Вы удивлены, увидев это? и кричать, что вы написалиbug
, Ха-ха.
На самом деле это не означает, что наше обычное суждениеbug
, необходимо проверить, достаточно ли точны наши потребности, чтобы распознать все редкие слова. Судя по привычкам пользователя, вероятность ввести эти необычные слова не очень высока, поэтому с обратной связью от мелких партнеров проблем не возникает.
Решить проблему перехвата эмодзи
Ближе к дому ведь нам еще предстоит решить поднятую в начале проблему, как правильно перехватить содержимоеemoji
Нить? отсюда изUTF-16
Кодирование, чтобы начать с.
UTF-16
UTF-16 конкретно определяет, как символы Unicode могут быть доступны на компьютерах. UTF-16 использует два байта для представления формата преобразования Unicode.Это метод представления с фиксированной длиной.Независимо от того, какой символ может быть представлен двумя байтами, два байта составляют 16 бит, поэтому он называется UTF-16. UTF-16 очень удобен для представления символов.Каждые два байта представляют один символ, что значительно упрощает работу при работе со строками.Это также очень важная причина, по которой Java использует UTF-16 в качестве формата хранения символов в памяти.
Кодовые точки в базовой многоязычной плоскости (диапазон кодовых точек от U+0000 до U+FFFF)UTF-16
В кодировке используется 1 символ, и его значение такое же, какUnicode
равны (преобразовывать не нужно), это наш обычный китайский иероглиф, например, кодовая точка во вспомогательной плоскости (диапазон кодовых точек U+10000-U+10FFFF) находится вUTF-16
кодируется как пара16bit
Кодовый блок (т.е. 32 бит, 4 байта), называетсясуррогатная пара. Первый из двух символов, составляющих суррогатную пару, называетсясвинцовые суррогатыДиапазон0xD800-0xDBFF
, последний называетсяследовые суррогатыДиапазон0xDC00-0xDFFF
surrogate
упомянутый вышеsurrogate
,surrogate
является значение агентства, понятие происходит не отJava
язык, но изUnicode
Один из методов кодированияUTF-16
. Подробнее см.:UTF-16
короче,Java
Информация о символах в рамках использования языкаUTF-16
кодирование. так какchar
Этот тип16-bit
из. это может иметь65536
ценность, то есть65536
Каждое число может представлять 1 символ. но,Unicode
содержит гораздо больше символов, чем65536
Кусок.那么编号大于65536
Да, пользуюсь до сих пор16-bit
Кодирование, что делать? тогдаUnicode
То, что придумала группа по установлению стандартов, заключалось в следующем:65536
номер, снять2048
, оговорив, что они「Surrogates」
, пусть они будут группой из двух для представления чисел больше, чем65536
Эти персонажи.
Точнее, числоU+D800
кU+DBFF
указывается как「High Surrogates」
,общий1024
Кусок. НетU+DC00
кU+DFFF
указывается как「Low Surrogates」
,Слишком1024
Кусок. Когда они появляются в комбинации, они могут выражать больше1048576
вид персонажей.
Причина эмодзи перехвата исключения
Выше приведены некоторые концептуальные знания.Если действительно легко запутаться, давайте оглянемся назад и начнем с кода:
мы можем поставитьemoji
выделяются следующим образом:
🐳 ->\uD83D\uDC33
🐳 ->\uD83D\uDC33
🐠 ->\uD83D\uDC20
emoji
определенно больше, чем65536
, так что здесь мы используем「High Surrogates」
и「Low Surrogates」
представлены в комбинациях два на два.
вышеизложеннымUTF-16
Знание кодирования может сделать вывод, что нашиemoji
Возьмите смайликchar
Причина искажения символов послеUTF-16
Кодирование суррогатных пар во вспомогательной плоскости, и если мы разделим суррогатные пары при перехвате, возникнет нештатная проблема.
Для этого случая мы можем пройтиCharacter
Класс Статический методisHighSurrogate
иisLowSurrogate
судить, одинemoji
Комбинациявысокий + низкий, поэтому для суррогатной пары во вспомогательной плоскости ее можно полностью убрать или оставить.
isHighSurrogate
Исходный код метода выглядит следующим образом:
public static final char MIN_HIGH_SURROGATE = '\uD800';
public static final char MAX_HIGH_SURROGATE = '\uDBFF';
public static boolean isHighSurrogate(char ch) {
return ch >= MIN_HIGH_SURROGATE && ch < (MAX_HIGH_SURROGATE + 1);
}
Это суждение на самом деле выше「High Surrogates」
, мы можем преобразовать его в:
U+D800 <= ch <= U+DBFF
Так же,isLowSurrogate
Метод определяется таким же образом:
U+DC00 <= ch <= U+DFFF
проблема решена
Или сначала запустите код, чтобы увидеть эффект:
Конкретный код реализации выглядит следующим образом:
public static void main(String[] args) {
// 用户昵称为:🐳🐳🐠,正常结果应该为:🐳***🐠
String context = "\uD83D\uDC33\uD83D\uDC33\uD83D\uDC20";
int realNameLength = realStringLength(context);
String namePrefix = subString(context, 1, 0);
String nameSuffix = subString(context, realNameLength - 1, 1);
context = String.format("%s%s%s", namePrefix, "***", nameSuffix);
System.out.println(context);
}
/**
* 包含emoji表情的subString方法
*
* @param str 原有的str
* @param len str长度
* @param type type = 0 代表prefix,其他代表suffix
*/
private static String subString(String str, int len, int type) {
if (len < 0) {
return str;
}
int count = 0;
for (int i = 0; i < str.length(); i++) {
if (count == len) {
// type = 0 代表prefix,其他代表suffix
if (type == 0) {
return str.substring(0, i);
}
return str.substring(i);
}
char c = str.charAt(i);
if (Character.isHighSurrogate(c) || Character.isLowSurrogate(c)) {
i++;
}
count++;
}
return str;
}
/**
* 包含emoji表情的字符串实际长度
*
* @param str 原有str
* @return str实际长度
*/
private static int realStringLength(String str) {
int count = 0;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (Character.isHighSurrogate(c) || Character.isLowSurrogate(c)) {
i++;
}
count++;
}
return count;
}
Пасхальное яйцо: забери свой смайлик
emoji
гораздо больше, чем это,unicode
Он также может поддерживатьemoji
Пожертвовать, конечно этоemoji
будет назван в честь донора. Существуют следующиеСписок пожертвований:
Я видел, что первый был пожертвован elastic.co, и, нажав на ссылку, можно перейти прямо на их официальный сайт. Еще один во втором списке пожертвований был пожертвован моим коллегой, ха-ха, очень интересно.
Если вы хотите пожертвовать себя, вы также можете перейти непосредственно кСайт пожертвований эмоджиПерейдите к заполнению личной информации, всего шестеренок три, после пожертвования в этом списке будут отображаться определенные вамиemoji
Информация такая классная 😎:
Суммировать
крошечныйemoji
Это действительно бесконечные знания. Из-за проблем с пространством я опустил здесь много вещей, таких какUTF-8
иUTF-16
Две формы кодирования и не более глубокое объяснение, там будет включать много контента.
Я надеюсь, что эта статья сделаетБросание кирпичей и привлечение нефритаРоль вдохновлять друзей на совместное изучение новых тайн.
Ссылаться на
- Википедия Юникод:Это. Wikipedia.org/wiki/u Нико…
- Википедия Unicode Character Plane Map:Это. Wikipedia.org/wiki/u Нико…
- Не стоит недооценивать крошечные смайлики:nuggets.capable/post/684490…
- Разговор о кодировках характера: Unicode, UTF-8 и CHAR []:mess.horse/post/insert AC…
- Проблема искажения выражения эмодзи, вызванная усечением символов:супер серия для взрослых.GitHub.IO/2018/06/19/…
- Список пожертвований смайликов:Woohoo.Unicode.org/consortium/…