Как вычислять кодировку при помощи статистики

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

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

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

И одна из самых больших проблем одновременно является самой простой: компьютеры не договорились о том, как записывать буквы двоичным кодом.

Как записываются буквы двоичным кодом


Возьмём для примера символ латиницы «A». В American Standard Code for Information Interchange, или ASCII, ему назначено число 65. Такая нумерация была унаследована Unicode, только в Unicode число 65 записывается в шестнадцатеричном виде (U+0041). Такую запись называют «элементом кодового пространства» (codepoint).

Здесь всё довольно просто; по крайней мере, в вопросе числа, обозначающего «A», в целом есть консенсус. Но компьютеры не могут просто хранить десятичные числа, они хранят только двоичные.

В самой популярной кодировке символов UTF-8 номер символа 65 («A») записывается так:

01000001

Равны единице, или «включены» только второй и последний биты. Второй бит обозначает 64, а последний — 1. В сумме они дают 65. Всё очень просто.

Ещё одна популярная кодировка — это UTF-16, в основном применяемая в мире Windows, Java и
JavaScript. В UTF-16 число 65 записывается следующим образом:

01000001 00000000

Практически то же самое, только UTF-16 использует под каждый символ два полных байта (как минимум), но не требует дополнительных битов для описания 65, так что второй байт остаётся пустым.

А что там с другими кодировками? Вот лишь некоторые из наиболее популярных:

  • Win-1252 — не относящаяся к Unicode кодировка, применяется там, где говорят на европейских языках
  • KOI8 — не относящаяся к Unicode кодировка, используется там, где применяется кириллица
  • GB18030 — Unicode, но в основном применяется в континентальном Китае
  • Big5 — не относится к Unicode, широко используется там, где применяются традиционные китайские иероглифы
  • Shift_JIS — не относится к Unicode, используется в Японии

Все эти кодировки наследуют от букв ASCII, поэтому во всех них A записывается так:

01000001

Точно так же, как в UTF-8.

Очень удобно. Именно поэтому базовый западноевропейский алфавит читаем, даже когда остальная часть документа превращается в исковерканный хаос. Многие популярные кодировки (за исключением UTF-16) соответствуют ASCII, по крайней мере, для латиницы.

Пока всё неплохо. Но давайте теперь рассмотрим более сложный символ: знак евро, €. Консорциум Unicode обозначил его числом 8364 (U+20AC).

В UTF-8 число 8364 представляется в следующем виде:

11100010 10000010 10101100

Обратите внимание, что в UTF-8 оно занимает три байта. UTF-8 — это кодировка символов с «переменной длиной»: чем больше число Unicode, тем больше байтов требуется. (На самом деле это справедливо и для UTF-16, но встречается реже.)

Однако в UTF-16 число 8364 кодируется совершенно иначе:

10101100 00100000

Win-1252 не следует стандарту Unicode. В этой кодировке знак евро имеет номер 128. И кодировка записывает 128 вот так:

10000000

То есть лишь один включённый бит равен 128.

И вот здесь начинаются проблемы. Как только мы покидаем спокойные улочки английского алфавита, кодировки быстро становятся хаотичными.

невозможно никак представить в KOI8.

В GB18030 символ € кодируется так:

10100010 11100011

В Big5 символ € выглядит так:

10100011 11100001

В Shift JIS это

10000000 00111111

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

Как определить, какая кодировка используется?


Некоторые форматы сами задают кодировку, например, JSON обязует применять UTF-8. Это сильно упрощает жизнь — если ты знаешь, что данные записаны в JSON, то они должны быть закодированы в UTF-8.

В других случаях можно передать кодировку отдельно. HTTP позволяет помещать кодировку в заголовок Content-Type:

Content-type: text/html; charset=ISO-8859-1

А у некоторых форматов есть внутренние способы указания кодировки. Например, у некоторых текстовых файлов есть заголовок:

# -*- encoding: utf-16be -*-

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

Ну а если у данных нет никаких меток?

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

В частности, у файлов CSV нет внутреннего способа информирования о том, какая кодировка в них использована. В них нельзя поместить комментарий, потому что для этого нет места, и программы чтения csv чаще всего не смогут распарсить ваш csv. А многие популярные инструменты, работающие с файлами CSV (MS Excel), не используют UTF-8.

Что будет тогда?

Решением будет статистика.

Определение кодировки при помощи статистики


Существует две базовые стратегии для определения кодировки неразмеченной строки текста.

  1. На уровне байтов
  2. На уровне символов

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

▍ Эвристики уровня байтов


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

Например, как я говорил выше, в UTF-16 используется по два байта на символ (чаще всего). В случае текста на латинице (например, английского) обычно появляется множество «пустых» вторых байтов. К счастью, во многих языках разметки активно используется латиница (например, <, >, [, ] и так далее), даже если сам документ составлен не на латинице. Если строка текста содержит множество пустых вторых байтов, то есть вероятность, что это UTF-16.

Существуют и другие признаки. Представьте, что вы веб-браузер, и ссылка перенесла пользователя к файлу, два первых байта которого имеют следующий вид:

00111100 00100001

Если бы это был UTF-16, то эти два байта оказались бы символом ℼ, имеющим название double struck small pi и номер 8508 (U+213C) в Unicode. Часто ли этот символ первым встречается в файле HTML?

Или более вероятно, что это двухсимвольная последовательность <! в кодировке UTF-8? Возможно, следующие байты — это doctype> или стандартный бойлерплейт любого документа HTML?

Ещё одна подсказка — это конкретные байты. Как ни ужасно, UTF-16 имеет две версии: в одной биты записываются обычным образом, в другой — в обратную сторону. Чтобы люди различали эти две версии, в стандарте UTF-16 есть маркер последовательности байтов (byte order mark), который можно поместить перед текстовым потоком, чтобы обозначить используемую версию. Эта пара байтов редко встречается в других кодировках, и практически никогда не бывает в начале, так что они становятся хорошей подсказкой о том, что идёт за ними.

Итак, байты могут дать нам довольно много информации о кодировке. Если вы можете с их помощью однозначно определить UTF-8 или UTF-16, то наша задача выполнена.

▍ Эвристики уровня символов


Сложности возникают с однобайтовыми кодировками, не относящимися к Unicode. Например, сложно отличить Win-1252 от KOI8, ведь для кодирования разных вещей и та, и другая используют обычно пустой первый бит ASCII.

Как же их отличить? Благодаря частотному анализу. Мы смотрим на буквы, которые могли бы присутствовать в документе, например, если это KOI8, и задаёмся вопросом: «Действительно ли это типичное распределение букв для документа на кириллице?».

Вот базовый алгоритм:

  • Исключаем все кодировки, отсечённые предыдущими эвристиками уровня байтов
  • Для каждой оставшейся возможной кодировки X:
    • Парсим входные данные, как будто они были закодированы X
    • Сравниваем частотность символов в строке со значениями в известной таблице частотности
    • Опционально также сравниваем пары букв (например, qu) с известной таблицей частотности
    • Если они достаточно хорошо совпадают, то возвращаем X

  • В противном случае возвращаем ошибку

Часто таким образом можно также определить, на каком языке написан этот документ — именно благодаря этому веб-браузеры открывают диалоговое окно «Перевести эту страницу?».

Действительно ли это работает?


Обычно люди не очень любят эвристики, но ответом является «да». Это работает, и на удивление хорошо. И намного лучше, чем просто предположения о том, что текст закодирован UTF-8 (в конечном итоге это и является бенчмарком).

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

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

Может показаться логичным, что если вы экспортируете лист Excel в файл csv в последней версии MS Excel, то получите UTF-8. Ну, или, возможно, UTF-16. Но вы ошибётесь. По умолчанию, в большинстве конфигураций Excel сохраняет CSV в кодировке Win-1252.

Win-1252 — это однобайтная кодировка, не относящаяся к Unicode. Это расширение ASCII, засовывающее в неиспользованный восьмой бит достаточно большое количество символов для почти каждого европейского языка. Обычный пользователь Excel никогда о ней не слышал, если вообще слышал о кодировках символов. Во многой мудрости много печали.

Дополнительные источники


Вероятно, основная часть кода определения кодировок работает на принципах, заложенных Netscape в начале 2000-х. Статья с описанием этого подхода есть в архиве Mozilla.

У меня есть чёткое впечатление, что автоматическое определение кодировки текста — это частный случай закона Постела: «будь консервативным в том, что делаешь, будь либерален в том, что принимаешь от других». Я всегда воспринимал закон Постела как что-то истинное, но сейчас у меня возникает всё больше сомнений. Возможно, механизм автоматического определения кодировки в моей базе данных csvbase стоит сделать частью пользовательского интерфейса, а не заранее выбранным пунктом выпадающего списка.

Telegram-канал со скидками, розыгрышами призов и новостями IT ?

Комментарии (61)


  1. Evengard
    02.05.2024 13:31

    Вспоминается вот этот вот ресурс: https://2cyr.com/decode/

    А нет чего-то open-source-ного для этого?


    1. okhsunrog
      02.05.2024 13:31

      Есть утилита iconv. Да и в том же vim/neovim можно поменять кодировку. Писал как-то пост про это в свой тг канал, если интересно - скину вам сообщением ссылку на пост. В принципе, всё это можно и самому нагуглить, просто у меня более "разжёвано".

      З.Ы. Статью смотрел по диагонали. У iconv нет автоопределения кодировки, но можно перебрать 2-3 самые распространённые кодировки в рунете - с большой вероятностью будет одна из них. А можно обернуть iconv в простенький python-скрипт, который будет фрагмент текста переводить используя разные кодировки, останется лишь выбрать кодировку, после которой текст больше всего похож на правду.


      1. datacompboy
        02.05.2024 13:31
        +14

        пост про это в свой тг канал

        ++enc=cp1251 уже требует пост в тг канал?


        1. okhsunrog
          02.05.2024 13:31

          В принципе, всё сводится к :e ++enc=cp1251 и :w ++enc=utf-8 Я всего лишь подобнее описал работу с iconv из консоли и преобразование в UTF-8 всех файлов в заданной директории и во всех вложенных директориях рекурсивно. Встала такая задача полгода назад, и родился пост, поделиться опытом, так сказать. Понятно, что опытным юзерам тут всё понятно как 2 пальца, я больше для новичков писал :)


          1. datacompboy
            02.05.2024 13:31
            +8

            Родился пост, в неиндексируемом месте, там где никто никогда не увидит... Чтобы что? :)


            1. okhsunrog
              02.05.2024 13:31
              +1

              Хороший вопрос :) Ну, канал с заметками, человек 100 увидели. На статьи для Хабра такие заметки не тянут. Возможно, стоит попробовать новую фичу Хабра – посты. А вот интересно, они индексируются Яндексом/Гуглом?


              1. datacompboy
                02.05.2024 13:31
                +2

                Да


      1. roqin
        02.05.2024 13:31
        +1

        Ну вот ХЗ, всю жизнь (когда мне было лень указать явно кодировку, т.е. достаточно часто) - я использую enconv и не жужжу (какие-то самописные скрипты не нужны).


      1. LorHobbit
        02.05.2024 13:31
        +1

        Кроме iconv, есть ещё enca. Iconv есть в любом линуксе, а enca надо ещё поискать и скорее всего собрать, зато в нём есть АВТООПРЕДЕЛЕНИЕ! Я как-то в рамках рефакторинга очень-очень старого легаси-проекта (часть авторов писали в 1251, часть в КОИ8) натравил на дерево исходников связку find и enca, и она успешно всё перевела в UTF8.

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

        https://github.com/nijel/enca


    1. BasilioCat
      02.05.2024 13:31
      +10

      Уже никому не нужны странные кодировки, все сожрал UTF-8 (иногда UTF-16). Лет 10 назад были chardet/chardetect/enca


      1. Dotarev
        02.05.2024 13:31
        +1

        Я давеча из-под Win 11 запустил bat файл, в ключ программы передал текст на русском. И очень удивился. Вот как вы думаете, в какой кодировке должен быть bat, чтобы ключ был передан корректно в .net приложение?


        1. DMGarikk
          02.05.2024 13:31
          +4

          866? консоль винды насколько я помню довольно забавная штука


          1. Dotarev
            02.05.2024 13:31

            Bingo!


        1. fddima
          02.05.2024 13:31
          +1

          Так, как настроена система. Есть же понятие ACP (ANSI Code Page). Вот в региональных настройках можно выбрать желаемую, щас по моему флажок для utf8 есть. Можно в реестре по старинке. Кодовая страница для utf8 - 65001.

          cmd-файлы в ansi и соотв должны следовать настройкам системы.


          1. Dotarev
            02.05.2024 13:31

            Спасибо, теперь я знаю про команду chcp.


    1. fekrado
      02.05.2024 13:31
      +8

      А я вспомнил shtirlitz . Хорошая программа была


      1. exTvr
        02.05.2024 13:31

        О даа, восстановить/подобрать кодировку в закраказябленном письме!



    1. demoth
      02.05.2024 13:31

      Есть uchardet, которая для длинных текстов довольно неплохо определяет кодировку.


  1. petropavel
    02.05.2024 13:31
    +19

    Такое впечатление, что автор этого поста, да и переводчик, зашли в какую-то пещеру лет 20 назад и только недавно проснулись. По крайней мере 20 лет назад я в последний раз писал автоопределение кодировок. Да и бнопню видел в последний раз примерно тогда же


    1. DMGarikk
      02.05.2024 13:31
      +5

      Да и бнопню видел в последний раз примерно тогда же

      А это не обязательно видеть, достаточно столкнутся с тем что какойто софт не работает с файлами которые лежат в C:\Пользователи\Документы Васяна\Какойто-Хлам\Самыйнужный файлик 123.docx ( для любителей похейтить винду - /home/vasyan/Документы Васяна/Какойто-Хлам/Самыйнужный файлик 123.docx )

      и такого софта внезапно больше чем хотелось бы


      1. vadimr
        02.05.2024 13:31
        +4

        Обозначенная проблема, скорее всего, связана с пробелом, а не с кодировками.


        1. DMGarikk
          02.05.2024 13:31
          +3

          а чем вам пробел не символ?

          вообще проблема не только с пробелом, софт зачастую не признает ничего кроме ascii символов

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


          1. vadimr
            02.05.2024 13:31
            +2

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

            В macOS, кстати, можно символ "/" использовать в видимых именах файлов в файндере, а в файловой системе это ":". Тоже раздолье, спасает только то, что мало кто так файлы называет.


        1. VBKesha
          02.05.2024 13:31

          Пару месяцев назад помогал другу решать проблему с русским путем, для какойто Java IDE не помню уже какой. Не хотела работать если в имени пользователя были русские буквы(темп она там хранила). Оказалось была в системе выбрана англиская кодировка для приложений не Unicode.


    1. Panzerschrek
      02.05.2024 13:31
      +1

      Какая-нибудь Visual Studio до сих пор наровит сохранить файл в CP1251, если там кириллические символы затесались.


      1. mayorovp
        02.05.2024 13:31

        Она делает интереснее: сохраняет в utf-8 если кириллические символы были сразу, и в системной кодировке если их не было. Когда они появляются - кодировка файла не меняется (сама кодировка определяется по наличию BOM).


        1. Panzerschrek
          02.05.2024 13:31
          +2

          Ну да, поэтому я если надо, сохраняю фал с кириллицей через Notepad++, а уже потом открываю его в Visual Studio.

          Но меня удручает, почему студия всё ещё лезет за какой-то там системной кодировкой. И вообще не ясно, зачем эта системная кодировка нужна, почему там всё по умолчанию не в UTF-8.


        1. deelayka
          02.05.2024 13:31
          +1

          От этого спасает файл .editorconfig в корне проекта, в нём можно задать кодировку и окончания строк для файлов по умолчанию, студия его понимает. Ну и компилятору добавить опцию /utf-8, чтобы исходники трактовались как UTF-8 без необходимости добавлять BOM.


      1. perfect_genius
        02.05.2024 13:31

        А ещё Visual Studio до сих пор не умеет показывать кириллические символы в подсказках при наведении курсора на #define. Если определить #define тэст тэст2, при наведении на "тэст" высветится #define тэст \u0442\u044d\u0441\u04422.


    1. LorHobbit
      02.05.2024 13:31

      Надо же, а мне всего 2 года назад (не 20) прислали для отладки моего редактора контактов файл .VCF, сгенерированный аутлуком. И там, внезапно, оказалась cp1251. Хотя во всех RFC на vCard прописан UTF8.

      Разработчики Qt вот тоже, видимо, 20 лет бнопни не видели. И в Qt 6.0 выкинули все неюникодные кодировки, а заодно и класс QTextCodec перевели в устаревшие. Уже в 6.4 их убедили вернуть поддержку всего, что поддерживает ICU... но уже в новые классы, которые изначально были заточены только на юникод. Козу купили, козу продали, но несовместимостей успели наломать.


    1. Harwest
      02.05.2024 13:31
      +1

      Автор поста ещё почему-то отсчитывает номера знакомест в двоичных числах слева направо.


    1. makapohmgn
      02.05.2024 13:31
      +3

      Вот буквально сегодня firefox показал мне кракозябры вместо русского текста в текстовых файлах, причём раньше в меню Вид можно было выбрать кодировку руками, но они это убрали почему-то)


  1. vadimr
    02.05.2024 13:31
    +25

    Настолько удивительная статья, что пришлось посмотреть биографию автора. Она всё и объясняет. Англичанин, год назад переехавший в Финляндию. Человек открыл для себя мир за пределами 26 букв.

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


    1. Antra
      02.05.2024 13:31
      +6

      Англичанин, год назад переехавший в Финляндию

      переживает, что

       невозможно никак представить в KOI8.

      "Мне бы его проблемы" (c)


      1. zaiats_2k
        02.05.2024 13:31
        +3

        Вот англичанин, молодец, рассматривает вариант что придётся в Финляндии к KOI8 привыкать. А финны как бессмерные себя ведут. ;)


  1. buratino
    02.05.2024 13:31
    +7

    Сложности возникают с однобайтовыми кодировками, не относящимися к Unicode. Например, сложно отличить Win-1252 от KOI8, ведь для кодирования разных вещей и та, и другая используют обычно пустой первый бит ASCII.

    пустой, да еще и первый бит...

    По умолчанию, в большинстве конфигураций Excel сохраняет CSV в кодировке Win-1252.

    аааа

    Win-1252 — это однобайтная кодировка, не относящаяся к Unicode. Это расширение ASCII, засовывающее в неиспользованный восьмой бит достаточно большое количество символов для почти каждого европейского языка.

    теперь этот пустой первый бит стал восьмым и неиспользуемым...


  1. edrokov
    02.05.2024 13:31
    +3

    Примерно 25 лет назад я попробовал натренировать самодельную нейросеть на распознавание кодировок. Обучалась на пентиуме примерно пару часов. Определяла на удивление точно по 20 символам текста.


    1. maxlilt
      02.05.2024 13:31

      Любопытно... А если файл начинался с псевдографики?


      1. petropavel
        02.05.2024 13:31
        +5

        досовская 866, очевидно :)


      1. edrokov
        02.05.2024 13:31
        +1

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


  1. mefepe
    02.05.2024 13:31

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


    1. kvazimoda24
      02.05.2024 13:31

      Любой стандарт обладает фатальным недостатком


    1. perfect_genius
      02.05.2024 13:31
      +2

      Unicode возник не так? Т.е. одарённые не взяли ASCII и не расширили её?


  1. Panzerschrek
    02.05.2024 13:31
    +1

    Вот кстати, а какой толк сейчас использовать UTF-16 (обе версии)?
    Насколько я понимаю, 16-битные кодировки родились тогда, когда наивно полагали, что 16 бит хватит всем. Тогда же появился wchar_t, до сих пор использующийся в WinAPI. Тогда же в Java и JavaScript строки сделали 16-битными.

    Но потом оказалось, что таки нужно сильно больше символов, чем полагалось ранее и UTF-16 стало не хватать, из-за чего появились суррогатные пары. В этом свете не понятно, какие ещё преимущества осталось у этого способа представления - он требует больше памяти в сравнении с UTF-8 для в основном латинских текстов, да к тому же существует проблема порядка байт.


    1. mayorovp
      02.05.2024 13:31
      +1

      Вот кстати, а какой толк сейчас использовать UTF-16 (обе версии)?

      Вот вы сами и ответили на свой вопрос: wchar_t до сих пор используется в WinAPI


    1. LAutour
      02.05.2024 13:31
      +2

      какие ещё преимущества осталось у этого способа представления

      Всегда быстрый произвольный доступ к символам по их индексам\смещению, в отличии от UTF-8.


      1. datacompboy
        02.05.2024 13:31
        +4

        В том и дело, что с момента появления суррогатных пар -- это больше не произвольный доступ к символам по индексам. Больше нельзя узнать длину строки в символах через длину в байтах.
        Вам следует перечитать диссертацию "О роли музыкальных инструментов в жизни домашних животных".


    1. vanxant
      02.05.2024 13:31

      Поломать всё win- , jvm- и веб-апи? Чтобы что?

      Тут пахнет экстремизмом:)


  1. Zara6502
    02.05.2024 13:31

    Равны единице, или «включены» только второй и последний биты

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


    1. slonopotamus
      02.05.2024 13:31
      +3

      Я извиняюсь, с какой стороны у байта лево?


      1. vikarti
        02.05.2024 13:31
        +2

        Сверху


      1. salnicoff
        02.05.2024 13:31
        +4

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


      1. Zara6502
        02.05.2024 13:31

        Быстрый ответ:

        • Биты в байте нумеруются справа налево от 0 до 7.


  1. vikarti
    02.05.2024 13:31

    Здесь всё довольно просто; по крайней мере, в вопросе числа, обозначающего «A», в целом есть консенсус.

    Да? Точно есть? :)

    А ничего что https://util.unicode.org/UnicodeJsps/character.jsp?a=0410 это «А»? И визуально отличить А от A - не очень просто.


    1. vanxant
      02.05.2024 13:31
      +1

      Есть ещё заглавная греческая альфа, она тоже выглядит как А. В большинстве шрифтов это один и тот же глиф (векторный рисунок)


  1. AntonLarinLive
    02.05.2024 13:31
    +1

    ФНС до сих пор все свои форматы клепает в расово-верном православном win-1251. Про UTF-8 они видимо не слышали. И всё бы хорошо, но только до первого клиента с национальными буквами в названии, не попадающими в 1251.


  1. ps1961
    02.05.2024 13:31
    +3

    Вообще-то вместе с WIN1252 стоило бы упомянуть что у Windows в GUI одна кодировка, в cmd другая. Для примера в русской обычно стоит 1251, а в консоли 866. Что кое когда приводит к очень забавным случаям


  1. perfect_genius
    02.05.2024 13:31

    Тем временем самый популярный браузер не даёт просто скопировать ссылку на какую-нибудь страницу самой популярной интэрнэт-энциклопедии и вставить её в нормальном виде.

    Это такой позор, что слов нет.

    Читал, что Опера определяла такой момент и не уродовала ссылку.


  1. breninsul
    02.05.2024 13:31

    UTF-16, в основном применяемая в мире Windows, Java и JavaScript

    Не, не втягивайте Java в это.


    1. mayorovp
      02.05.2024 13:31

      Не втягивать? А какая тогда там кодировка в строках применяется?