Кодировки текста и символы перевода строки в Windows — основы искажения кодировки и CRLF/LF

· · Windows, Кодировки символов, Искажение кодировки, Символы перевода строки, UTF-8, CP932, PowerShell, Unicode

В консультациях о работе с текстом в Windows следующие темы очень часто путаются между собой сразу все вместе.

  • В чём разница между Shift_JIS и UTF-8
  • Почему возникает искажение кодировки
  • В чём разница между CRLF и LF
  • Файл перевели в UTF-8, но почему он всё равно иногда не читается
  • Почему один и тот же файл выглядит по-разному в редакторе, консоли, Excel и Git

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

К тому же в Windows до сих пор сосуществуют мир Unicode и мир кодовых страниц. Добавьте сюда BOM, символы перевода строки, автоопределение кодировки в редакторе, кодовую страницу консоли и преобразование переводов строк в Git — и тема начинает выглядеть запутанной.

В этой статье мы разберём, с практической точки зрения, часто путаемые в Windows Shift_JIS / UTF-8 / UTF-16, причины возникновения искажения кодировки, разницу между CRLF и LF, а также то, почему эта тема так легко приводит к путанице.

Материал опирается на открытые данные Microsoft Learn, PowerShell, Git, W3C / Unicode по состоянию на апрель 2026 года. Подробности см. в списке источников в конце статьи.

Содержание

  1. Что важно понять в первую очередь
  2. Разбираем терминологию
    • 2.1 В чём разница между Unicode / UTF-8 / UTF-16 / CP932
    • 2.2 Как относиться к Shift_JIS и CP932
    • 2.3 Ловушки терминов ANSI, Unicode и UTF-8N
  3. Почему возникает искажение кодировки
    • 3.1 Что такое искажение кодировки на самом деле
    • 3.2 Искажение отображения и повреждение данных — разные вещи
    • 3.3 Приведение к непредставимым символам необратимо
  4. В чём разница между символами перевода строки
    • 4.1 CRLF / LF / CR
    • 4.2 Перевод строки — вопрос, отдельный от кодировки
    • 4.3 \n и байты перевода строки в файле не всегда совпадают
  5. Почему в Windows особенно легко запутаться
    • 5.1 Unicode и устаревшие кодовые страницы сосуществуют
    • 5.2 Названия не согласованы
    • 5.3 Если текст только ASCII, проблема остаётся незаметной
    • 5.4 Содержимое файла, имя файла, консоль и исходный файл — разные уровни
    • 5.5 BOM и символы перевода строки действуют по отдельной оси
    • 5.6 Инструменты меняют всё сами
  6. Типичные сценарии сбоев
  7. Правила, снижающие число сбоев на практике
  8. Расследование искажения кодировки и различий в переводах строк ведём по этим 5 вопросам
  9. Итог
  10. Похожие статьи
  11. Источники

1. Что важно понять в первую очередь

Если сразу перечислить главное, важны следующие семь пунктов.

  • Текстовый файл состоит не из самой строки, а из байт + кодировки + символов перевода строки. Иногда к этому добавляется ещё и BOM.
  • Искажение кодировки возникает, когда одни и те же байты декодируются в другой кодировке.
  • Проблемы с переводом строки возникают, когда кодировка верна, но не совпадает предположение о разделителе строк.
  • Unicode и UTF-8 — не одно и то же. Unicode относится к набору символов, а UTF-8 и UTF-16 — это кодировки (encoding).
  • То, что в Windows называют «Shift_JIS», на практике безопаснее воспринимать как CP932 / японскую кодовую страницу семейства Windows — так разговор меньше расходится.
  • Одной фразы «перешли на UTF-8» для спецификации недостаточно. Правилом эксплуатации это становится только тогда, когда решены и наличие BOM, и тип перевода строки.
  • Источник путаницы — не сам японский язык, а сосуществование на одной Windows нескольких предположений с разной историей.

При работе с текстом в Windows отправная точка — разделить следующие четыре момента.

  1. Какие байты содержит этот файл
  2. В какой кодировке он был записан
  3. В какой кодировке он был прочитан
  4. CRLF или LF используется для перевода строки

Уже одно это разделение заметно снижает вероятность запутаться.

2. Разбираем терминологию

2.1 В чём разница между Unicode / UTF-8 / UTF-16 / CP932

Сначала быстрее всего один раз разобрать термины по отдельности.

Термин Что обозначает Пример Частая путаница
Unicode Система представления символов в виде номеров U+3042 () Считают тем же самым, что UTF-8
UTF-8 Кодировка, переводящая Unicode в байты E3 81 82 Считают самим Unicode
UTF-16LE Кодировка, переводящая Unicode в байты 42 30 Путают с пунктом меню «Unicode»
CP932 Устаревшая японская кодовая страница Windows 82 A0 Считают полностью идентичной Shift_JIS
CRLF / LF Байты-разделители строк 0D 0A / 0A Считают разновидностью кодировки
BOM Идентифицирующие байты в начале файла EF BB BF и т. п. Считают названием самой кодировки

Например, даже для одного символа байты различаются в зависимости от кодировки.

Символ: あ

UTF-8    : E3 81 82
CP932    : 82 A0
UTF-16LE : 42 30

Важно понимать: символ и байты — разные вещи. На экране приложение работает с тем, что выглядит как «символы», но при сохранении и передаче в конечном счёте обмен идёт байтами. Сбои чаще всего происходят именно на границе этого преобразования.

2.2 Как относиться к Shift_JIS и CP932

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

Если хочется точнее обозначить устаревший японский текст Windows, безопаснее думать о нём как о CP932, или японской кодовой странице семейства Windows.

Если отнестись к этому небрежно, начинаются вот такие расхождения в разговоре.

  • Вы сказали «сохрани в Shift_JIS», а собеседник имел в виду CP932 со стороны Windows
  • На стороне Linux / macOS файл обработали как shift_jis, но часть файлов, пришедших из Windows, не воспроизводится корректно
  • Было сказано «сохранить в ANSI», но то, какая это кодовая страница, зависело от окружения

Поэтому в спецификациях и заметках при расследовании безопаснее по возможности писать так.

  • Не Shift_JIS, а CP932
  • Не ANSI, а ACP (active code page) / в японском окружении обычно CP932
  • Не просто text, а конкретно, например UTF-8 no BOM, LF

2.3 Ловушки терминов ANSI, Unicode и UTF-8N

Вокруг Windows источником путаницы становятся и сами словесные обозначения.

Особенно сбивают с толку следующие три.

  • ANSI — встречается в интерфейсе Windows и в старых описаниях, но это не ASCII. Чаще всего под этим подразумевается активная кодовая страница данной машины.
  • Unicode — в некоторых редакторах и инструментах пункт меню Unicode на деле означает UTF-16LE. Фраза «сохранил в Unicode» не обязательно означает UTF-8.
  • UTF-8N — встречается в редакторах, распространённых в японоязычной среде; обычно это лишь ярлык интерфейса для обозначения UTF-8 без BOM, а не официальное название кодировки.

Иными словами, в Windows один и тот же термин у разных инструментов означает разное. Это первая крупная точка путаницы.

3. Почему возникает искажение кодировки

3.1 Что такое искажение кодировки на самом деле

Суть искажения кодировки довольно проста.

  1. Строка кодируется (encode) в байты в некоторой кодировке
  2. Эти байты декодируются (decode) обратно в строку в другой кодировке
  3. Если предположения не совпадают, получается другая строка

Например, если сохранить в UTF-8, байты будут такими.

E3 81 82

Если прочитать их как UTF-8, получится , а если исходить из предположения CP932 — они будут выглядеть как другая строка, вроде 縺�. В этом случае повреждён не «японский текст», а предположение о decode.

Если сформулировать искажение кодировки одной строкой, получится так.

Одни и те же байты прочитали как другую кодировку.

3.2 Искажение отображения и повреждение данных — разные вещи

Здесь важно разделять стадию, когда всё ещё можно восстановить, и стадию, когда восстановить уже трудно.

Например, при следующей последовательности действий восстановление ещё возможно.

  1. Файл в UTF-8 открывают как CP932
  2. На экране это выглядит как 縺�
  3. Файл ещё не был сохранён

На этой стадии исходные байты по-прежнему остаются в UTF-8. Если заново открыть файл в правильной кодировке, содержимое может восстановиться.

Опасна следующая последовательность действий.

  1. Файл в UTF-8 неверно читают как CP932
  2. Содержимое, которое выглядит искажённым, сохраняют как есть
  3. Исходные байты UTF-8 теряются

На этом этапе речь уже идёт не об искажении отображения, а о повреждении данных.

На практике важно не сводить всё к одной фразе «файл искажён», а как минимум разделять следующие два вопроса.

  • Остаются ли сами байты корректными
  • Было ли уже пересохранено неверно прочитанное содержимое

3.3 Приведение к непредставимым символам необратимо

Ещё одна опасная ситуация — приведение строки Unicode к узкой кодовой странице вроде CP932.

Если строка содержит символы, отсутствующие в целевой кодировке, происходит одно из следующего.

  • Символ заменяется на ?
  • Вставляется символ-заменитель
  • Возникает ошибка преобразования
  • Символ заменяется на другой, похожий

Например, некоторые эмодзи и расширенные иероглифы напрямую в CP932 не переводятся. Такой сбой нужно оценивать не по критерию «читается или нет», а по тому, возвращается ли исходное значение после обратного преобразования (round-trip).

Однажды утраченную информацию не восстановить, даже узнав впоследствии правильную кодировку.

4. В чём разница между символами перевода строки

4.1 CRLF / LF / CR

Перевод строки — это тоже байты.

  • CR = carriage return = 0D
  • LF = line feed = 0A
  • В текстовых файлах Windows традиционно используется CRLF (0D 0A)
  • В Linux / Unix обычно используется LF (0A)
  • Одиночный CR иногда встречается в старых контекстах вроде классических Mac

В виде таблицы это выглядит так.

Перевод строки Байты Основной контекст
CRLF 0D 0A Традиционные текстовые файлы Windows, устаревшие инструменты
LF 0A Linux / macOS / большинство инструментов разработки
CR 0D Довольно старые устаревшие данные

4.2 Перевод строки — вопрос, отдельный от кодировки

Это довольно важный момент.

Символ перевода строки — вопрос, отдельный от кодировки.

Даже в одном и том же файле UTF-8 перевод строки может быть как CRLF, так и LF. Например, для содержимого «A, перевод строки, B» байты будут различаться так.

UTF-8 + LF   : 41 0A 42
UTF-8 + CRLF : 41 0D 0A 42

То есть вполне обычная ситуация, когда:

  • UTF-8, но отличается только перевод строки
  • CP932, но перевод строки — LF
  • UTF-16LE, но перевод строки — CRLF

Поэтому когда говорят «перешли на UTF-8, но всё равно не то», на деле иногда расходится не кодировка, а только перевод строки.

4.3 \n и байты перевода строки в файле не всегда совпадают

Именно здесь программисты незаметно для себя чаще всего путаются.

То, что в исходном коде написано \n, ещё не значит, что в файле обязательно окажется только 0A. В текстовом режиме (text mode) языка, среды выполнения или I/O API символ \n в Windows иногда преобразуется в CRLF.

То есть возможно расхождение между следующим.

  • Представление перевода строки в исходном коде
  • Строка во время выполнения
  • Байты, сохранённые в файле
  • Перевод строки, видимый в редакторе

Из-за этого случаются сбои вроде «я был уверен, что написал LF, но в файле оказался CRLF».

Современные редакторы прекрасно работают с одним лишь LF, но у сопутствующих инструментов, устаревших приложений и бизнес-процессов предположение о CRLF всё ещё сохраняется. Поэтому проблема перевода строки — не «дела давно минувших дней», она и сегодня регулярно встречается на практике.

5. Почему в Windows особенно легко запутаться

5.1 Unicode и устаревшие кодовые страницы сосуществуют

Это главная причина, по которой в Windows всё так запутано.

В Windows сохраняются оба пути:

  • обработка через Unicode
  • обработка на основе кодовых страниц

Более новые приложения, веб и кросс-платформенные ресурсы тяготеют к UTF-8, тогда как в старых CSV, TXT, логах, вокруг Excel и в интеграции бизнес-систем сохраняется CP932. Кроме того, в части вывода и вокруг некоторых API вполне обычным делом остаётся и UTF-16LE.

Иными словами, на одной машине с Windows сосуществует сразу несколько текстовых культур.

5.2 Названия не согласованы

Путаницу усиливает не столько сама технология, сколько несогласованность названий.

  • Говорят «Shift_JIS», а по факту это CP932
  • Говорят «ANSI», а по факту это активная кодовая страница
  • Говорят «Unicode», а по факту это UTF-16LE
  • Говорят «UTF-8», но по факту наличие или отсутствие BOM не определено
  • Появляются собственные ярлыки редакторов вроде UTF-8N

Если оставить это без уточнения, разговор внешне выглядит слаженным, но реальное содержание не совпадает.

5.3 Если текст только ASCII, проблема остаётся незаметной

Это тоже значимый фактор.

Поскольку UTF-8 совместим с диапазоном ASCII, файл, содержащий только латинские буквы, цифры и символы, иногда «более-менее читается» даже при неверном предположении о кодировке. На стороне CP932 диапазон, эквивалентный ASCII, тоже редко выглядит искажённым внешне, поэтому проблема не всплывает на поверхность.

В результате складывается такая картина.

  • Конфигурационный файл только на английском выглядит без проблем
  • Стоит добавить одну строку японского текста, как всё ломается
  • Проблема, скрывавшаяся всё это время, впервые проявляется уже в эксплуатации

Поэтому сбои кодировки часто выглядят так, будто «вчера всё работало, а сегодня вдруг сломалось». На деле чаще всего оказывается, что мина была заложена давно, а проявилась она лишь в момент появления не-ASCII символов.

5.4 Содержимое файла, имя файла, консоль и исходный файл — разные уровни

В Windows легко запутаться, если объединить всё нижеперечисленное одним термином «кодировка».

  • Имя файла / путь
  • Содержимое файла
  • Отображение в консоли
  • Кодировка самого файла исходного кода
  • Формат строк во время выполнения
  • Отображение в буфере обмена и элементах GUI

Например, даже если японское имя файла отображается нормально, содержимое самого файла может быть сохранено в CP932. И наоборот: даже если сам файл в UTF-8, при несовпадении кодовой страницы консоли исказится только отображение.

Такие операции, как chcp 65001, в основе своей влияют лишь на предположение на стороне консоли и не меняют байты уже существующего файла.

Более того, даже если файл исходного кода в UTF-8, лог-файл, записываемый во время выполнения, не обязательно окажется тоже в UTF-8. Каждый раз нужно чётко разделять, о кодировке какого именно уровня идёт речь.

Кстати, в японской Windows символ \ иногда отображается как знак иены, и это тоже легко путают с вопросом кодировки. Однако в большинстве случаев это проблема отображающего шрифта или глифа, а не изменение смысла разделителя пути или экранирующего символа.

5.5 BOM и символы перевода строки действуют по отдельной оси

Одного лишь слова «UTF-8» достаточно только для половины дела.

На практике важны и следующие моменты.

  • Есть BOM или нет
  • CRLF или LF используется для перевода строки

Например, даже в рамках одного и того же UTF-8:

  • есть инструменты Windows, которые читают файл только при наличии BOM
  • есть обработка на стороне Unix, где из-за BOM в первом столбце появляются лишние символы
  • есть устаревшие инструменты, которым трудно работать с одиночным LF
  • при CRLF могут портиться shell-скрипты и diff’ы

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

5.6 Инструменты меняют всё сами

Ещё сложнее то, что используемые инструменты меняют содержимое неявно, сами по себе.

  • Редактор автоматически определяет кодировку
  • При сохранении добавляет или убирает BOM
  • Git преобразует CRLF / LF
  • Оболочка или команда сохраняет файл в кодировке по умолчанию
  • Экспорт CSV использует неожиданную кодовую страницу
  • В разных версиях PowerShell и других инструментов различаются значения по умолчанию

То есть даже если исполнитель ничего явно не указывал, на практике в Windows какой-то из слоёв сам добавляет своё предположение.

Это и есть истинная причина ситуации «я ничего не менял, а всё сломалось». На деле нередко меняет не человек, а значения по умолчанию инструмента.

6. Типичные сценарии сбоев

Типичные сбои в виде таблицы выглядят так.

Ситуация Что на самом деле расходится Типичный симптом
Устаревший инструмент Windows принимает конфигурационный файл UTF-8 no BOM за ANSI / CP932 Предположение о decode Искажается только японский текст
CSV в CP932 передают в систему, работающую по предположению UTF-8 Предположение о decode , ошибка decode, бессмысленный японский текст
Лог в UTF-16LE передают в текстовый инструмент Unix Предположение о кодировке Примешиваются NUL-байты, файл выглядит как бинарный
Файл исходного кода в LF в другом окружении преобразуют в CRLF Предположение о переводе строки Огромный diff по концам строк, сбои в скриптах
Неверно прочитанное содержимое сохраняют как есть Сами байты превращаются в нечто иное Необратимое повреждение данных
В спецификации написано только «выгрузить CSV» Интерфейс не определён Excel читает, а другой инструмент ломается
Решили лишь «унифицировать на UTF-8» BOM / перевод строки не определены Не срабатывают только отдельные инструменты

Особенно опасен сценарий, при котором увидев искажённое отображение, содержимое сохраняют как есть, тем самым окончательно закрепляя сбой.

7. Правила, снижающие число сбоев на практике

Далее речь пойдёт о том, какие правила эксплуатации стоит определить, чтобы снизить число сбоев.

7.1 Определяем базовый вариант для новых файлов

Для новых файлов разумно в первую очередь выбирать UTF-8 в качестве базового варианта. Но одного этого недостаточно.

Как минимум безопаснее определить ещё и следующее.

  • UTF-8 with BOM или UTF-8 no BOM
  • CRLF или LF для перевода строки
  • Кто будет читать этот файл
  • Нужна ли совместимость с устаревшими инструментами Windows
  • Будут ли читать файл также Linux / macOS / CI / контейнеры

Например, для исходного кода и конфигурации, рассчитанных на кросс-платформенность, первым кандидатом обычно становится UTF-8 no BOM + LF. С другой стороны, если нужно подстроиться под старые инструменты Windows или существующую эксплуатацию, иногда всё ещё необходимы UTF-8 with BOM или CP932 + CRLF.

Важно принимать решение исходя не из общих рассуждений «что правильно», а из того, с кем именно происходит обмен данными.

7.2 Не меняем существующие legacy-файлы по своей инициативе

Если существующий файл в CP932, безопаснее не переводить его в UTF-8 заодно с повседневной небольшой правкой.

Безопасная схема эксплуатации выглядит так.

  • Существующие файлы сохраняют исходную кодировку / BOM / перевод строки
  • Преобразование кодировки выделяется в отдельную задачу миграции
  • Массовое преобразование выполняется только после проверки объектов конвертации и downstream-потребителей

Сбои с искажением кодировки нередко начинаются с благих намерений — «заодно модернизировать».

7.3 Рассматриваем кодировку и перевод строки как часть интерфейса

Для CSV, TXT, логов, конфигурационных файлов и простых протоколов интерфейсом является не только содержимое, но и сам формат текста.

В спецификации безопаснее указать как минимум следующее.

  • Кодировка
  • Наличие BOM
  • Тип перевода строки
  • Наличие заголовка
  • Правила экранирования / разделителя
  • Каким инструментом проводилась проверка

Например, одних лишь трёх букв CSV недостаточно. Только когда написано UTF-8 with BOM, CRLF, разделитель — запятая, с заголовком, разговор перестаёт расходиться.

7.4 Явно указываем кодировку на границах чтения и записи

На стороне кода тоже безопаснее не полагаться на неявные значения по умолчанию.

  • При чтении / записи файла явно указывать кодировку
  • Учитывать кодировку и при передаче текста между процессами
  • В процедурах экспорта / импорта фиксировать в спецификации и перевод строки
  • Не делать небрежное перенаправление оболочки продуктивным путём передачи данных

Особенно в Windows «удалось сохранить» и «сохранилось с правильными байтами» — не одно и то же.

7.5 Делимся правилами Git и редактора

Git — не инструмент, который автоматически исправляет кодировку. При этом для line endings преобразование иногда всё же происходит.

Поэтому безопаснее определить следующее на уровне репозитория.

  • Использовать ли LF как основной вариант для исходного кода
  • Допускать ли CRLF для текста, предназначенного только для Windows
  • Как зафиксировать это в .gitattributes
  • Как делиться настройками редактора

Важно рассматривать кодировку и line endings отдельно друг от друга. Даже если Git приводит переводы строк к единому виду, сбои с кодировкой никуда не денутся.

7.6 Не останавливаемся на «файл искажён» — говорим, что именно разошлось

На практике хорошо помогает такая замена формулировок.

  • Плохая формулировка: «файл искажён»
  • Хорошая формулировка: «похоже, файл UTF-8 no BOM открывают с предположением CP932»
  • Плохая формулировка: «с концами строк что-то не так»
  • Хорошая формулировка: «файл в LF преобразуется в CRLF, из-за чего растёт diff»

Уже одна лишь способность назвать, что именно разошлось, заметно ускоряет расследование.

8. Расследование искажения кодировки и различий в переводах строк ведём по этим 5 вопросам

Если расследование зашло в тупик, быстрее всего вернуться к следующим пяти вопросам.

  1. Какие байты сейчас содержит этот файл
    • Это UTF-8?
    • UTF-8 с BOM?
    • CP932?
    • UTF-16LE?
  2. Кто и с каким предположением записал файл первым
    • Редактор?
    • Устаревшее приложение?
    • Экспорт из Excel?
    • Оболочка / скрипт?
    • Batch-процесс / промежуточное ПО?
  3. Кто и с каким предположением читает файл сейчас
    • Автоопределение редактора?
    • Кодовая страница консоли?
    • Кодировка по умолчанию в библиотеке?
    • Спецификация на стороне импорта?
  4. Что представляют собой BOM и перевод строки
    • BOM есть или нет
    • CRLF или LF
  5. Было ли уже сохранено неверно прочитанное содержимое
    • Это пока только отображение?
    • Или файл уже пересохранён и байты утрачены?

Когда ответы на эти пять вопросов найдены, причина, как правило, становится видна.

9. Итог

Кодировки и символы перевода строки в Windows выглядят запутанными не потому, что сложен сам японский язык. Причина в том, что байты, кодировка, BOM, перевод строки и значения по умолчанию инструментов существуют независимо друг от друга, а вдобавок в Windows сосуществуют старая и новая текстовые культуры.

Особенно стоит запомнить следующие шесть пунктов.

  • Искажение кодировки — результат чтения одних и тех же байт в другой кодировке
  • Проблема перевода строки лежит в плоскости, отдельной от кодировки
  • Не стоит слишком доверять словам Shift_JIS, CP932, ANSI, Unicode буквально
  • Одной фразы «перешли на UTF-8» недостаточно, нужны ещё BOM и тип перевода строки
  • Искажение отображения и уже сохранённое повреждение данных нужно рассматривать раздельно
  • В спецификации писать не просто text, а конкретно, например UTF-8 no BOM, LF

Иными словами, при работе с текстом в Windows практичнее считать это не «вопросом строк», а вопросом того, как согласовать договорённость о байтах.

10. Похожие статьи

11. Источники

  1. Microsoft Learn, Code Page Identifiers - Win32 apps https://learn.microsoft.com/en-us/windows/win32/intl/code-page-identifiers
  2. Microsoft Learn, about_Character_Encoding - PowerShell https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_character_encoding?view=powershell-7.6
  3. Microsoft Learn, Understanding file encoding in VS Code and PowerShell https://learn.microsoft.com/en-us/powershell/scripting/dev-cross-plat/vscode/understanding-file-encoding?view=powershell-7.6
  4. W3C Internationalization, Character encodings: Essential concepts https://www.w3.org/International/articles/definitions-characters/
  5. Git documentation, gitattributes https://git-scm.com/docs/gitattributes
  6. Git documentation, git-config https://git-scm.com/docs/git-config

Недавние статьи с теми же тегами помогут подробнее изучить близкие темы.

Задачи планировщика заданий Windows не запускаются или завершаются с 0x1 — диагностика причин и проектирование надёжного выполнения по расписанию

Разбираем принципы проектирования надёжного выполнения задач по расписанию в Windows: учётные записи выполнения и типы входа в систему, т...

Эти страницы показывают тему статьи в более широком контексте услуг и решений.

Статья напрямую связана со следующими услугами.

Технические консультации и ревью дизайна

В проектах, где предположения о кодировке CSV, логов и конфигурационных файлов расходятся между Windows и Linux, заблаговременное упорядочивание I/O-контракта и правил эксплуатации помогает снизить число инцидентов.

Частые вопросы

Вопросы, которые часто возникают при консультациях по теме статьи.

Почему возникает искажение кодировки?
Потому что одна и та же последовательность байт была прочитана в кодировке, отличной от той, в которой она была записана. Например, если сохранить символ «あ» в UTF-8, получится последовательность байт E3 81 82, но при чтении в контексте CP932 она превратится в другую строку вроде «縺». В этом случае повреждён не японский текст, а предположение о decode. При этом если сохранить неверно прочитанное содержимое поверх исходного файла, исходные байты будут утрачены, и это станет уже не искажением отображения, а повреждением данных — поэтому важно переоткрыть файл в правильной кодировке ещё до сохранения.
В чём разница между CRLF и LF?
Это разница в байтах, которыми обозначается разделитель строк. CRLF — это два байта 0D 0A, традиционно используемые в текстовых файлах Windows, а LF — один байт 0A, распространённый в Linux / macOS и большинстве инструментов разработки. Важно понимать, что перевод строки — это вопрос, отдельный от кодировки: в одном и том же файле UTF-8 перевод строки может быть как CRLF, так и LF, поэтому фраза «перешли на UTF-8, но всё равно не то» иногда означает, что разошлась не кодировка, а только тип перевода строки.
Shift_JIS и CP932 — это одно и то же?
Для разговора этого достаточно, но на практике безопаснее их различать. Если хочется точнее обозначить устаревший японский текст Windows, лучше думать о нём как о CP932 или о японской кодовой странице семейства Windows. Аналогично, обозначение «ANSI» в Windows чаще всего означает активную кодовую страницу данной машины, а пункт меню «Unicode» в некоторых редакторах на деле означает UTF-16LE. В спецификациях и заметках при расследовании стоит писать конкретно, например «UTF-8 no BOM, LF», а не расплывчатые названия.
Что нужно зафиксировать в спецификации текстового файла?
Одной фразы «перешли на UTF-8» недостаточно — правилом эксплуатации это становится только тогда, когда решены ещё и наличие BOM, и тип перевода строки. Для файлов обмена вроде CSV и логов безопаснее прописать вплоть до кодировки, наличия BOM, перевода строки, наличия заголовка и правил разделителя. Для исходного кода и конфигурации, рассчитанных на кросс-платформенность, первым кандидатом обычно становится UTF-8 no BOM + LF, а если нужно подстроиться под старые инструменты Windows, иногда всё ещё необходимы UTF-8 with BOM или CP932 + CRLF.

Об авторе

Страница с профилем автора статьи.

Го Комура

Представитель KomuraSoft LLC

Специализируется на разработке программного обеспечения для Windows, техническом консалтинге и расследовании сбоев, особенно в проектах с унаследованными системами и трудно воспроизводимыми ошибками.

Публичные ссылки

Вернуться в блог