Проблема кодировок часто возникает при написании парсеров, чтении данных из xml и CSV файлов. Ниже представлены способы эту проблему решить.
1
windows-1251 в UTF-8
$text = iconv('windows-1251//IGNORE', 'UTF-8//IGNORE', $text);
echo $text;
PHP
$text = mb_convert_encoding($text, 'UTF-8', 'windows-1251');
echo $text;
PHP
2
UTF-8 в windows-1251
$text = iconv('utf-8//IGNORE', 'windows-1251//IGNORE', $text);
echo $text;
PHP
$text = mb_convert_encoding($text, 'windows-1251', 'utf-8');
echo $text;
PHP
3
Когда ни что не помогает
$text = iconv('utf-8//IGNORE', 'cp1252//IGNORE', $text);
$text = iconv('cp1251//IGNORE', 'utf-8//IGNORE', $text);
echo $text;
PHP
Иногда доходит до бреда, но работает:
$text = iconv('utf-8//IGNORE', 'windows-1251//IGNORE', $text);
$text = iconv('windows-1251//IGNORE', 'utf-8//IGNORE', $text);
echo $text;
PHP
4
File_get_contents / CURL
Бывают случаи когда file_get_contents()
или CURL возвращают иероглифы (ÐлмазнÑе боÑÑ) – причина тут не в кодировке, а в отсутствии BOM-метки.
$text = file_get_contents('https://example.com');
$text = "\xEF\xBB\xBF" . $text;
echo $text;
PHP
Ещё бывают случаи, когда file_get_contents() возвращает текст в виде:
�mw�Ƒ0�����&IkAI��f��j4/{�</�&�h�� ��({�o�����:/��<g���g��(�=�9�Paɭ
Это сжатый текст в GZIP, т.к. функция не отправляет правильные заголовки. Решение проблемы через CURL:
function getcontents($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_ENCODING, 'gzip');
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$output = curl_exec($ch);
curl_close($ch);
return $output;
}
echo getcontents('https://example.com');
PHP
12.01.2017, обновлено 02.11.2021
Другие публикации
Отправка e-mail в кодировке UTF-8 с вложенными файлами и возможные проблемы.
JSON (JavaScript Object Notation) – текстовый формат обмена данными, основанный на JavaScript, который представляет собой набор пар {ключ: значение}. Значение может быть массивом, числом, строкой и…
Описание значений глобального массива $_SERVER с примерами.
Так как Instagram и Fasebook ограничили доступ к API, а фото с открытого аккаунта всё же нужно периодически получать и…
В статье представлены различные PHP-расширения для чтения файлов XLS, XLSX, описаны их плюсы и минусы, а также примеры…
Примеры как зарегистрировать бота в Телеграм, описание и взаимодействие с основными методами API.
REPA
Функция на языке Си для конвертации строк из кодировки UTF-8 в Windows-1251 (CP1251)
Файл с функцией: https://github.com/0x1801/REPA/blob/main/utf8_2_win1251.c
- Поставляется в виде исходного кода.
- Написана на языке С.
- Может быть использована в программах на языке C++.
- Может применяться в программах для микроконтроллеров
- Не использует ни SIMD-инструкций, ни даже x64.
- Использует очень мало памяти: 1 массив на 32 байта (компилятор кладет его в векторный регистр, если он есть) + несколько констант.
- Поддерживает символы utf8 до 4х байт (стандарт RFC 3629)
- Входной массив может совпадать с выходным: данные будут перезаписаны.
Применение:
Вам ничего не понадобится, кроме текста функции и 3х макросов перед ней. Ни инклюдов и библиотек, ни массивов, никакого другого кода. Просто скопируйте ее в свой проект.
ВНИМАНИЕ: Функция требует наличия 2х лишних выделенных байтов памяти за символом конца строки во входном массиве с символами utf8. В этих байтах может лежать любой мусор. Обычно, если в вашем проекте код написан оптимально, то вы не будете каждый раз выделять память под строку. Поэтому выделить 2 лишних байта — это не проблема. Но если в вашем проекте сложно это внедрить, то можете немного самостоятельно модифицировать код.
Если есть желание проверить работу функции, можно написать тест самостоятельно или воспользоваться заготовкой из main.c: https://github.com/0x1801/REPA/blob/main/main.c
Больше main.c ни для чего не нужен.
БОНУС: в файле https://github.com/0x1801/REPA/blob/main/koi8r_2_windows1251_AVX512.c можно найти функцию конвертации из любой 8-битной ASCII-совместимой кодировки в любую 8-битную ASCII-совместимую кодировку, написанную с использованием векторных инструкций AVX512. В коде для примера реализована конвертация из koi8r в windows 1251, но алгоритм пригоден для конвертации любоых сочетаний 8-битных кодировок, совместимых с ASCII. Признаюсь честно, что сам я ее тестировать поленился, т.к. msvc 2015 «из коробки» не знает функций, которые я использовал. Функция, как минимум, компилируется (в коментарии к ней ссылка на godbolt.org). Просто мне было интересно написать функцию, которая умеет конвертировать сразу 64 символа всего за 12 инструкций (само отображение занимает при этом вообще 2 инструкции). Если вам удастся протестировать функцию или найти в ней ошибки (или улучшения), напишите мне, пожалуйста.
Связаться с автором:
Илья
chronosphere@mail.ru.
Конвертирует строку из UTF-8 в Windows-1251
static string UTF8ToWin1251(string sourceStr)
{
Encoding utf8 = Encoding.UTF8;
Encoding win1251 = Encoding.GetEncoding(«Windows-1251»);
byte[] utf8Bytes = utf8.GetBytes(sourceStr);
byte[] win1251Bytes = Encoding.Convert(utf8, win1251, utf8Bytes);
return win1251.GetString(win1251Bytes);
}
Конвертирует строку из Windows-1251 в UTF-8
static private string Win1251ToUTF8(string source)
{
Encoding utf8 = Encoding.GetEncoding(«utf-8»);
Encoding win1251 = Encoding.GetEncoding(«windows-1251»);
byte[] utf8Bytes = win1251.GetBytes(source);
byte[] win1251Bytes = Encoding.Convert(win1251, utf8, utf8Bytes);
source = win1251.GetString(win1251Bytes);
return source;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
#include <stdlib.h> #include <stdio.h> #include <string.h> #define LINE_MAX 1024 int convert_utf8_to_windows1251(const char* utf8, char* windows1251, size_t n); int main(int argc, char ** argv) { //printf("start %s\n", argv[0]); if (argc <= 1) { printf("forgot file name for conversion"); exit(EXIT_FAILURE); } FILE* file = fopen(argv[1], "r"); if (!file) { perror("can't open file"); exit(EXIT_FAILURE); } while(!feof(file)) { char buff[LINE_MAX] = {0}; if (!fgets(buff, LINE_MAX, file)) { perror("can't read line from file"); exit(EXIT_FAILURE); } char output[LINE_MAX] = {0}; if (!convert_utf8_to_windows1251(buff, output, LINE_MAX)) { printf("can't convert line: %s\n", buff); exit(EXIT_FAILURE); } printf("%s", output); }; return EXIT_SUCCESS; } typedef struct ConvLetter { char win1251; int unicode; } Letter; static Letter g_letters[] = { {0x82, 0x201A}, // SINGLE LOW-9 QUOTATION MARK {0x83, 0x0453}, // CYRILLIC SMALL LETTER GJE {0x84, 0x201E}, // DOUBLE LOW-9 QUOTATION MARK {0x85, 0x2026}, // HORIZONTAL ELLIPSIS {0x86, 0x2020}, // DAGGER {0x87, 0x2021}, // DOUBLE DAGGER {0x88, 0x20AC}, // EURO SIGN {0x89, 0x2030}, // PER MILLE SIGN {0x8A, 0x0409}, // CYRILLIC CAPITAL LETTER LJE {0x8B, 0x2039}, // SINGLE LEFT-POINTING ANGLE QUOTATION MARK {0x8C, 0x040A}, // CYRILLIC CAPITAL LETTER NJE {0x8D, 0x040C}, // CYRILLIC CAPITAL LETTER KJE {0x8E, 0x040B}, // CYRILLIC CAPITAL LETTER TSHE {0x8F, 0x040F}, // CYRILLIC CAPITAL LETTER DZHE {0x90, 0x0452}, // CYRILLIC SMALL LETTER DJE {0x91, 0x2018}, // LEFT SINGLE QUOTATION MARK {0x92, 0x2019}, // RIGHT SINGLE QUOTATION MARK {0x93, 0x201C}, // LEFT DOUBLE QUOTATION MARK {0x94, 0x201D}, // RIGHT DOUBLE QUOTATION MARK {0x95, 0x2022}, // BULLET {0x96, 0x2013}, // EN DASH {0x97, 0x2014}, // EM DASH {0x99, 0x2122}, // TRADE MARK SIGN {0x9A, 0x0459}, // CYRILLIC SMALL LETTER LJE {0x9B, 0x203A}, // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK {0x9C, 0x045A}, // CYRILLIC SMALL LETTER NJE {0x9D, 0x045C}, // CYRILLIC SMALL LETTER KJE {0x9E, 0x045B}, // CYRILLIC SMALL LETTER TSHE {0x9F, 0x045F}, // CYRILLIC SMALL LETTER DZHE {0xA0, 0x00A0}, // NO-BREAK SPACE {0xA1, 0x040E}, // CYRILLIC CAPITAL LETTER SHORT U {0xA2, 0x045E}, // CYRILLIC SMALL LETTER SHORT U {0xA3, 0x0408}, // CYRILLIC CAPITAL LETTER JE {0xA4, 0x00A4}, // CURRENCY SIGN {0xA5, 0x0490}, // CYRILLIC CAPITAL LETTER GHE WITH UPTURN {0xA6, 0x00A6}, // BROKEN BAR {0xA7, 0x00A7}, // SECTION SIGN {0xA8, 0x0401}, // CYRILLIC CAPITAL LETTER IO {0xA9, 0x00A9}, // COPYRIGHT SIGN {0xAA, 0x0404}, // CYRILLIC CAPITAL LETTER UKRAINIAN IE {0xAB, 0x00AB}, // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK {0xAC, 0x00AC}, // NOT SIGN {0xAD, 0x00AD}, // SOFT HYPHEN {0xAE, 0x00AE}, // REGISTERED SIGN {0xAF, 0x0407}, // CYRILLIC CAPITAL LETTER YI {0xB0, 0x00B0}, // DEGREE SIGN {0xB1, 0x00B1}, // PLUS-MINUS SIGN {0xB2, 0x0406}, // CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I {0xB3, 0x0456}, // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I {0xB4, 0x0491}, // CYRILLIC SMALL LETTER GHE WITH UPTURN {0xB5, 0x00B5}, // MICRO SIGN {0xB6, 0x00B6}, // PILCROW SIGN {0xB7, 0x00B7}, // MIDDLE DOT {0xB8, 0x0451}, // CYRILLIC SMALL LETTER IO {0xB9, 0x2116}, // NUMERO SIGN {0xBA, 0x0454}, // CYRILLIC SMALL LETTER UKRAINIAN IE {0xBB, 0x00BB}, // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK {0xBC, 0x0458}, // CYRILLIC SMALL LETTER JE {0xBD, 0x0405}, // CYRILLIC CAPITAL LETTER DZE {0xBE, 0x0455}, // CYRILLIC SMALL LETTER DZE {0xBF, 0x0457} // CYRILLIC SMALL LETTER YI }; int convert_utf8_to_windows1251(const char* utf8, char* windows1251, size_t n) { int i = 0; int j = 0; for(; i < (int)n && utf8[i] != 0; ++i) { char prefix = utf8[i]; char suffix = utf8[i+1]; if ((prefix & 0x80) == 0) { windows1251[j] = (char)prefix; ++j; } else if ((~prefix) & 0x20) { int first5bit = prefix & 0x1F; first5bit <<= 6; int sec6bit = suffix & 0x3F; int unicode_char = first5bit + sec6bit; if ( unicode_char >= 0x410 && unicode_char <= 0x44F ) { windows1251[j] = (char)(unicode_char - 0x350); } else if (unicode_char >= 0x80 && unicode_char <= 0xFF) { windows1251[j] = (char)(unicode_char); } else if (unicode_char >= 0x402 && unicode_char <= 0x403) { windows1251[j] = (char)(unicode_char - 0x382); } else { int count = sizeof(g_letters) / sizeof(Letter); for (int k = 0; k < count; ++k) { if (unicode_char == g_letters[k].unicode) { windows1251[j] = g_letters[k].win1251; goto NEXT_LETTER; } } // can't convert this char return 0; } NEXT_LETTER: ++i; ++j; } else { // can't convert this chars return 0; } } windows1251[j] = 0; return 1; } |
Привет, друзья. Я уже 3 года работаю с вебом, но с таким не встречался еще. В чем суть:
Есть у меня кириллический текст с кодировкой UTF-8 и отображается он нормально.
Мне нужно изменить кодировку на windows-1251 так, чтобы кириллический текст так же нормально читабельно отображался. И вот что-то ну вообще не могу взять в толк, как это сделать?
-
Вопрос задан
-
29548 просмотров
Пригласить эксперта
для большого количества файлов есть однострочник на powershell:
Get-ChildItem folderwithfiles -File | foreach {Get-Content $_.fullname -Encoding UTF8 | Out-File folderwithconvertedfiles\$_ -encoding default}
Одна загвоздка : encoding default — берет кодировку системы.
Проверить что это windows 1251 можно так(powershell) :[System.Text.Encoding]::Default.Codepage
Вы имеете в виду, самостоятельно, а не в программном коде? Тогда с помощью Вашего текстового редактора, которым Вы пользуетесь. Например, если Вы предпочитаете Sublime Text, то просто воспользуйтесь пунктом меню File->Save with encoding > Cyrillic (Windows 1251)
Войдите, чтобы написать ответ
-
Показать ещё
Загружается…