Дело в кодировке текста

внешний интерфейс HTML Unicode

Мы часто слышим обычный текстовый формат и двоичное кодирование, что такое обычный текст и что такое двоичное? Чтобы проиллюстрировать на примере. Создайте новый файл hello.txt со следующим содержимым:

hello, world

Этот файл имеет 12 байт:

С помощью Node.js вы можете увидеть, какое исходное двоичное хранилище этого файла находится на жестком диске.Следующий код:

let fs = require("fs");
// 读取原始二进制内容
let buffer = fs.readFileSync("hello.txt"); 
console.log(buffer);

После запуска консоль выводит 12 байт двоичного содержимого (отображается в шестнадцатеричном формате):

<Buffer 68 65 6c 6c 6f 2c 20 77 6f 72 6c 64>

Обращаясь к таблице ASCII, мы обнаруживаем, что эти числа являются просто кодами ASCII, соответствующими английскому языку, как показано на следующем рисунке:

Если этот текстовый файл читается в utf-8:

let fs = require("fs");
let text = fs.readFileSync("hello.txt", "utf-8"); 
console.log(text);

На выходе текст:

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

Как показано ниже:


Если считается, что это UTF-8, кодировка может соответствовать тексту. Как появился шрифт текста? Он находится внутри файла шрифта, в котором хранится форма каждого символа в векторном формате svg. Что такое кодировка UTF/UTF-8?

Кодировка UTF

1 байт может представлять всего 256 символов от 0 до (2^8 – 1). ASCII использует 7 бит для представления 128 символов, что соответствует требованиям современного английского языка. Как следует использовать специальные символы, азиатские языки и Emoj? представлены? Мы следуем описанному выше методу, чтобы увидеть, что хранятся в следующих файлах, содержащих символы китайского языка и эмодзи:

we 发 财 🤑

Как показано ниже:

Среди них кодировка пробела 20. Вы можете видеть, что английский по-прежнему занимает 1 байт, китайский использует 3 байта, а эмодж использует 4 байта. Как он узнает, сколько байтов он должен считывать каждый раз? Как показано ниже:

Если байт начинается с 0, это означает, что этот байт представляет символ, если он начинается с 3 единиц, это означает, что этот символ занимает 3 байта, а сколько единиц означает, сколько байтов занимает текущий символ. Это функция хранения UTF-8.UTF определяет количество каждого символа, а UTF-8 определяет, как должны храниться символы. отофициальный сайт юникодаМожно обнаружить, что кодировка UTF для «I» — 6211, как показано на следующем рисунке:

Как 6211 становится кодировкой utf-8? Потому что 6211 попадает в следующий диапазон:

U+ 0800 ~ U+ FFFF: 1110XXXX 10XXXXXX 10XXXXXX

Итак, это выглядит так:

«Мой» utf-8 — это E6 88 91, вы можете сравнить результат encodeURIComponent:

Можно сказать, что utf-8 делает utf реализованным, а utf-8 является наиболее широко используемым методом кодирования текста в Интернете. Помимо utf-8 и utf-16, отношение преобразования между ними и utf следующее:

UTF-8 
U+ 0000 ~ U+ 007F: 0XXXXXXX
U+ 0080 ~ U+ 07FF: 110XXXXX 10XXXXXX 
U+ 0800 ~ U+ FFFF: 1110XXXX 10XXXXXX 10XXXXXX 
U+10000 ~ U+10FFFF: 11110XXX 10XXXXXX 10XXXXXX 10XXXXXX

UTF-16 
U+0000 - U+FFFF         xxxxxxxx xxxxxxxx
U+10000 - U+10FFFF   110110xx xxxxxxxx 110111xx xxxxxxxx

Преимущество utf-8 в том, что английскому нужен только один байт, а китайскому - 3 байта.Преимущество utf-16 в том, что длина кодировки фиксированная, китайскому нужно всего два 2 байта, а английскому тоже нужно два слова Фестиваль. Следовательно, более выгодно использовать кодировку utf-8 для веб-страниц на английском языке, а кодировку utf-16 для китайских веб-страниц должно быть более выгодно. Потому что большинство китайцев используют коды от U+0000 до U+FFFF. Для таких символов, как Emoj, которые обычно не используются в конце, как utf-8, так и utf-16 требуется 4 байта. При этом utf-32 — это фиксированные 4 байта.

Полную кодировку UTF можно найти на официальном сайте, вот некоторые символы и диапазоны их кодировки, как показано на следующем рисунке:

Китайские иероглифы от 4E00 до 9FFF, их около 20 000. Кодировка FXXXX и 10XXXX предназначена для настройки, например, может использоваться для шрифтов значков, но шрифты значков обычно не используют этот диапазон, а используют более короткие кодировки, которые просто сопоставляются с другими обычными наборами символов, такими как традиционные символы, поэтому в качестве В результате система будет использовать шрифт по умолчанию перед загрузкой шрифта значка, и на странице сначала будут отображаться традиционные китайские символы, а затем восстановлен значок. Эта проблема возникает на телефонах Android.

Мы можем использовать кодировку UTF непосредственно в html, например:

Затем отобразится веб-страница:

Это также называется html-сущностью (сущностью), обычно используемой для экранирования специальных символов или шрифтов значков.

Затем мы поговорим об искаженных символах.

искаженный

Откройте двоичный файл в текстовом редакторе, например файл изображения:

Многие текстовые редакторы по умолчанию используют кодировку utf-8, например submlime:

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

Вот реальная проблема с искажением.Для сжатых пакетов Windows имя распакованного файла на Mac обычно искажено, как показано на рисунке ниже.Почему это?

Кодировка окон по умолчанию — ANSI, и следующие кодировки можно сохранить с помощью текстового редактора, входящего в состав Windows:

ANSI в соответствии с локалью, упрощенный китайский использует GBK. Что такое ГБК? GBK — местная кодировка китайского языка. Например, кодировка GBK для буквы «I» — CED2. Первоначальный стандарт кодирования китайского языка — GB2312, который включает более 6000 часто используемых китайских иероглифов. Позже был выпущен GBK, и традиционные китайские иероглифы были включен, а позже был выпущен GB18030, включающий языки этнических меньшинств.Различные отношения кодирования показаны на следующем рисунке:

Но программное обеспечение Mac обычно использует utf-8, китайский должен быть 3 байта, но сейчас только 2 байта, что не правильно, поэтому при распаковке он становится другим символом, что выглядит искаженным. На компьютерах Mac можно установить программу под названием unarchive, в которой есть алгоритмы автоматического определения кодировки символов:

С распакованными именами файлов проблем нет. Кроме того, многие редакторы кода обычно используют по умолчанию utf-8.Текст, сохраненный в текстовом редакторе, который поставляется с Windows, будет искажен при открытии в этом редакторе:

Когда выбран правильный метод кодирования, отображение будет нормальным:

Также часто встречается проблема с кодировкой текста, то есть возврат каретки и перевод строки.

возврат каретки и перевод строки

Метод разрыва строки Sublime по умолчанию основан на системных настройках, как показано в следующих настройках Sublime:

Из его комментариев также видно, что Windows использует CRLF, а Unix-системы используют LF:

CR: Возврат каретки (возврат каретки\r)

LF: перевод строки (перевод строки\n)

Другими словами, новая строка окон — это \r\n, а система Unix, такая как Mac, использует \n. В чем разница между возвратом каретки и переводом строки? Enter означает перемещение курсора в начало строки, а новая строка означает перемещение курсора на следующую строку. Если вы запустите следующий код в Node.js:

console.log("hello, world\rgoodbye, world");

Тогда будет выведено «до свидания, мир»:

«привет, мир» перезаписывается, это то, что делает возврат каретки. Позже, в целях экономии места, новая строка Unix будет только \n.

"\r" будет отображаться как ^M в git:

Иногда возникает другая проблема: при привязке хоста сообщение, скопированное из QQ, вставляется в файл хоста, в MAC может быть больше \r и это не подействует, а в винде может быть меньше \r проблем. может выглядеть как обычный разрыв строки в вашем редакторе.

Поговорим о длине строки.

длина строки

В строках Java и JS используется кодировка UTF-16, поскольку она имеет преимущество относительно фиксированной длины, в отличие от UTF-8, которая может изменять количество байтов от 1 до 4. Как показано ниже:

Длина английского и китайского языков равна 1, а длина Emoj равна 2, потому что единица длины составляет 2 байта как 1, а длина Emoj составляет 4 байта, поэтому длина равна 2.

Вы можете использовать charCodeAt для возврата кодировки utf текущего символа:

Если вы хотите определить китайский язык, вы можете использовать регулярные выражения, чтобы увидеть, попадает ли текущий символ в диапазон китайской кодировки:

В Mysql, если тип поля VARCHAR(10), он может хранить до 10 английских или 10 китайских символов.Если это поле использует кодировку utf-8 по умолчанию, оно должно учитывать 10 * 3 = 30 байт, если используется кодировка GBK, то необходимо использовать 10 * 2 = 20 байт.

тег метакодировки

Обычно мы добавляем мета-кодировку в тег заголовка страницы, указывающий метод кодирования текущей страницы:

<meta charset="utf-8">

В html4 это написано так:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Эти два работают одинаково, но последний устарел. Какая польза от этого кода?

В качестве исследования используется code.html:

<!DOCType html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    你好world
</body>
</html>

Затем пишем простейший сервер на Node.js:

let http = require("http");
let fs = require("fs");

http.createServer((req, res) => {
    let content = fs.readFileSync("./code.html", "utf-8");
    console.log(req.url);
    res.end(content);
}).listen("8125", err => {
    if (err) {
        console.log(err);
    } else {
        console.log("Server start, listening on http://localhost:8125");
    }
});

Запустите, а затем посетите localhost:8125, страница отображается нормально:

Теперь я меняю кодировку на gbk:

<meta charset="gbk">

Затем снова обновите страницу, это ненормально:
Но если я установлю кодировку заголовка ответа Content-Type на utf-8 на сервере Node.js:

res.setHeader("Content-Type", "text/html; charset=utf-8");

Этот заголовок ответа можно увидеть в консоли браузера:

Независимо от того, какая кодировка установлена ​​в метатеге, страница может отображаться нормально.

Таким образом, согласно нашему наблюдению, метатег будет работать только в том случае, если в заголовке ответа http не задана кодировка.


В этой статье обсуждается взаимосвязь между utf/utf-8/utf-16.utf — это международный стандарт, определяющий кодировку каждого символа, а utf-8/utf-16 определяет, как utf хранится и читается. в том, что он более выгоден для английского и экономит место, а utf-16 более выгоден для китайского. Но если западные страны используют utf-8, а затем восточные страны используют utf-16, то интернет может быть запутанным, поэтому мы все еще используем utf-8 с точки зрения единых стандартов. Также обсуждалась проблема кодировки GBK и искаженных символов.Если символ хранится в одной кодировке, но читается в другой кодировке, он не будет соответствовать исходным символам, и будут искаженные символы.условие. Кроме того, поскольку длина кодировки utf-16 относительно фиксирована, JS и Java используют utf-16 в качестве кодировки своих строк в памяти. Согласно эксперименту, тег charset мета работает, когда не задана кодировка заголовка ответа.

Короче говоря, кодировка символов — это большая тема, в этой статье в основном обсуждается та ее часть, которая имеет большое отношение к Сети, а также перечисляются некоторые проблемы, с которыми мы обычно сталкиваемся. Я считаю, что после прочтения этой статьи вы должны лучше понять кодировку текста.