Об авторе: nekron Ant Financial Data Experience Technology Team
задний план
Из-за широты и глубины китайского языка и несоответствия ранних кодировок файлов сейчас могут встречаться следующие кодировки файлов:GB2312
,GBk
,GB18030
,UTF-8
,BIG5
Ждать. Поскольку знание кодирования и декодирования является относительно низкоуровневым и непопулярным, у меня всегда было поверхностное понимание этих кодировков. Я часто задаюсь вопросом, является ли имя кодирования в верхнем или нижнем регистре, и необходимо добавить «-» между английским языком и цифры., которые сделали правила и т. Д.
Мое поверхностное понимание таково:
кодирование | иллюстрировать |
---|---|
GB2312 | Самый ранний упрощенный китайский код и зарубежная версия HZ-GB-2312. |
BIG5 | Традиционный китайский код, используемый в основном на Тайване. Искаженные символы некоторых традиционных китайских игр на самом деле вызваны неправильным использованием кодировки BIG5 и кодировки GB2312. |
GBK | Упрощенный + традиционный, я буду рассматривать его как GB2312 + BIG5, который не является национальным стандартом, но в основном соответствует китайской среде. Позже я узнал, что К на самом деле является первой буквой пиньинь, означающей «расширенный», что очень по-китайски. . . |
GB18030 | Новая версия семейства GB совместима, последний национальный стандарт, теперь китайское программное обеспечение должно поддерживать поддерживаемый формат кодирования, новый выбор декодирования файлов |
UTF-8 | Никаких объяснений, международный стандарт кодирования, html сейчас самый стандартный формат кодирования. |
Концепция кардинга
После долгого пребывания в яме у меня наконец появилось определенное понимание такого рода знаний, и теперь некоторые важные понятия переставлены следующим образом:
Прежде всего, чтобы усвоить все знания о кодировке и декодировании символов, мы должны сначала прояснить два понятия — набор символов и кодировка символов.
набор символов
Как следует из названия, это набор символов. Наиболее интуитивно понятное различие между различными наборами символов заключается в том, что количество символов различно. Общие наборы символов включают набор символов ASCII, набор символов GB2312, набор символов BIG5, набор символов GB18030, Unicode. набор символов и т.д.
Кодировка символов
Кодировка символов определяет метод сопоставления набора символов с фактическими двоичными байтами.Каждая кодировка символов имеет свои собственные правила проектирования, такие как фиксированное количество байтов или переменная длина, которые здесь не рассматриваются.
GB2312, BIG5, UTF-8 и т. д., которые часто упоминаются, если не указано иное, обычно относятся к кодировке символов, а не к набору символов.
Существует отношение «один ко многим» между наборами символов и кодировками символов.В одном наборе символов может существовать несколько кодировок символов.Типичными представителями являются UTF-8, UTF-16 и т. д. в наборе символов Unicode.
BOM (метка порядка байтов)
При использовании Блокнота Windows для сохранения файла в качестве метода кодирования можно выбрать ANSI (судя по локали, семейству GB в упрощенной китайской системе), Unicode, Utf-8 и т. д.
Чтобы прояснить концепцию, необходимо указать, что Unicode здесь, метод кодирования на самом деле UTF-16LE.
Как при таком количестве методов кодирования система Windows определяет, какой метод кодирования использовать при открытии файла?
Ответ: Windows (например: система упрощенного китайского языка) добавляет несколько байтов к заголовку файла, чтобы указать метод кодирования, три байта (0xef, 0xbb, 0xbf) указывают UTF-8; два байта (0xff, 0xfe) или 0xfe , 0xff) для UTF-16 (Unicode); нет для GB**.
Стоит отметить, что, поскольку спецификация не выражается, ее следует отбрасывать при разборе содержимого файла, иначе заголовок анализируемого содержимого будет иметь избыточное содержимое.
LE (с прямым порядком байтов) и BE (с прямым порядком байтов)
Это включает в себя знания, связанные с байтами, которые не находятся в центре внимания этой статьи, но будут объяснены попутно, когда они будут упомянуты. LE и BE обозначают порядок байтов, указывая, что байты начинаются с младшего/старшего соответственно.
Все процессоры, с которыми мы часто сталкиваемся, являются LE, поэтому Unicode в Windows по умолчанию относится к LE, если порядок байтов не указан.
В Buffer API узла есть две соответствующие функции для обработки LE и BE Документ выглядит следующим образом:
const buf = Buffer.from([0, 5]);
// Prints: 5
console.log(buf.readInt16BE());
// Prints: 1280
console.log(buf.readInt16LE());
Расшифровка узла
В первый раз, когда я столкнулся с проблемой такого типа, я использовал для ее решения узел, и в то время мне были предложены следующие варианты:
- node-iconv (пакет системных iconv)
- iconv-lite (чистый js)
Поскольку node-iconv включает в себя сборку node-gyp, а машиной для разработки является Windows, подготовка среды node-gyp и ряд последующих установок и сборок заставляют таких веб-разработчиков, как я, чувствовать боль (безумие), а не (сумасшествие) ( плюнуть)) Здорово (шумно) и в итоге выбрал iconv-lite естественно.
Процесс расшифровки примерно такой:
const fs = require('fs')
const iconv = require('iconv-lite')
const buf = fs.readFileSync('/path/to/file')
// 可以先截取前几个字节来判断是否存在BOM
buf.slice(0, 3).equals(Buffer.from([0xef, 0xbb, 0xbf])) // UTF-8
buf.slice(0, 2).equals(Buffer.from([0xff, 0xfe])) // UTF-16LE
const str = iconv.decode(buf, 'gbk')
// 解码正确的判断需要根据业务场景调整
// 此处截取前几个字符判断是否有中文存在来确定是否解码正确
// 也可以反向判断是否有乱码存在来确定是否解码正确
// 正则表达式内常见的\u**就是unicode码点
// 该区间是常见字符,如果有特定场景可以根据实际情况扩大码点区间
/[\u4e00-\u9fa5]/.test(str.slice(0, 3))
Интерфейсное декодирование
С ЕС20151Браузерные реализации становятся все более и более популярными, и стали возможны интерфейсные кодеки. Предыдущий процесс загрузки файлов на серверную часть для анализа содержимого через форму формы теперь может в основном обрабатываться интерфейсной частью, что не только снижает сетевое взаимодействие с серверной частью, но и делает работу пользователя более удобной. интуитивно понятный из-за обратной связи интерфейса.
Общий сценарий таков:
const file = document.querySelector('.input-file').files[0]
const reader = new FileReader()
reader.onload = () => {
const content = reader.result
}
reader.onprogerss = evt => {
// 读取进度
}
reader.readAsText(file, 'utf-8') // encoding可修改
Список кодировок, поддерживаемых FileReader, можно найти здесь.здесь.
Здесь есть интересное явление: если файл содержит спецификацию, например объявление кодировки UTF-8, указанная кодировка будет недействительной, а часть спецификации будет удалена из выходного содержимого, что более удобно для использования.
Если у вас есть более высокие требования к управлению кодировкой, вы можете преобразовать в вывод TypedArray:
reader.onload = () => {
const buf = new Uint8Array(reader.result)
// 进行更细粒度的操作
}
reader.readAsArrayBuffer(file)
После получения буфера данных текстового содержимого можно вызвать TextDecoder для продолжения декодирования, но следует отметить, что полученный TypedArray содержит BOM:
const decoder = new TextDecoder('gbk')
const content = decoder.decode(buf)
Если файл относительно большой, вы можете использовать фрагмент Blob для вырезания:
const file = document.querySelector('.input-file').files[0]
const blob = file.slice(0, 1024)
Разрыв строки файла несовместим с разными операционными системами.Если вам нужно разобрать строку за строкой, это зависит от сцены:
- Linux: \n
- Windows: \r\n
- Mac OS: \r
**Примечание.** Это правило текстового редактора по умолчанию в каждой системе. Если вы используете другое программное обеспечение, такое как обычно используемые sublime, vscode, excel и т. д., вы можете установить разрыв строки самостоятельно, обычно \ n или \r\n.
интерфейсное кодирование
Содержимое строки можно преобразовать в TypedBuffer с помощью TextEncoder:
const encoder = new TextEncoder()
encoder.encode(String)
Стоит отметить, что начиная с Chrome 53 кодировщик поддерживает только кодировку utf-8.2, официальная причина в том, что другие кодировки используются слишком мало. вотбиблиотека полифилла, который дополняет удаленный формат кодировки.
Файлы, сгенерированные внешним интерфейсом
После того, как интерфейсное кодирование завершено, генерация файла обычно реализуется в зависимости от ситуации.Пример кода выглядит следующим образом:
const a = document.createElement('a')
const buf = new TextEncoder()
const blob = new Blob([buf.encode('我是文本')], {
type: 'text/plain'
})
a.download = 'file'
a.href = URL.createObjectURL(blob)
a.click()
// 主动调用释放内存
URL.revokeObjectURL(blob)
Это создаст файл с именем file с суффиксом, определяемым типом. Если вам нужно экспортировать csv, вам нужно только изменить соответствующий тип MIME:
const blob = new Blob([buf.encode('第一行,1\r\n第二行,2')], {
type: 'text/csv'
})
Как правило, CSV открывается Excel по умолчанию.В это время будет обнаружено, что содержимое первого столбца искажено, потому что Excel следует логике кодирования суждения Windows (упомянутой выше), и когда спецификация не найдена, GB18030 кодирование используется для декодирования, что приводит к искажению контента.
В настоящее время вам нужно только добавить спецификацию, чтобы указать формат кодировки:
const blob = new Blob([new Uint8Array([0xef, 0xbb, 0xbf]), buf.encode('第一行,1\r\n第二行,2')], {
type: 'text/csv'
})
// or
const blob = new Blob([buf.encode('\ufeff第一行,1\r\n第二行,2')], {
type: 'text/csv'
})
Вот небольшое пояснение, потому что UTF-8 и UTF-16LE принадлежат к набору символов Unicode, но реализация отличается. Следовательно, с помощью определенных правил две кодировки могут быть преобразованы друг в друга, и преобразование спецификации, указывающей UTF-16LE, в кодировку UTF-8 фактически является спецификацией, указывающей UTF-8.
Прикрепил:
В этой статье рассказывается о кодировании и расшифровке символов. Заинтересованные студенты могут подписаться на эту колонку или отправить свое резюме по адресу 'tao.qit####alibaba-inc.com'.replace('####', '@').
Оригинальный адрес:GitHub.com/proto team/no…