Как конвертировать из windows 1251 в utf 8

Проблема кодировок часто возникает при написании парсеров, чтении данных из 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 в PHP

JSON (JavaScript Object Notation) – текстовый формат обмена данными, основанный на JavaScript, который представляет собой набор пар {ключ: значение}. Значение может быть массивом, числом, строкой и…

Массив $_SERVER

Описание значений глобального массива $_SERVER с примерами.

Получить фото из Instagram без API

Так как Instagram и Fasebook ограничили доступ к API, а фото с открытого аккаунта всё же нужно периодически получать и…

Обзор PHP расширений для чтения файлов Excel

В статье представлены различные PHP-расширения для чтения файлов XLS, XLSX, описаны их плюсы и минусы, а также примеры…

Бот Телеграм на PHP

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

У сайта есть:

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

При запуске кода:

response = requests.get('url', headers = {'UserAgent': UserAgent().Chrome})

print(response.text)

Ответ примерно такой:

<font face="Verdana"><font color="#FFFFCC" size="2">Óïðàæíåíèå XXVI/6: ãðóïïèðîâàíèå</font><br>

Если это сохранить при помощи:

with open('1.html', 'w', encoding='utf-8') as file:
    file.write(response.text)

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


  • Вопрос задан

  • 3608 просмотров

Оказалось что библиотека Requests кодирует данные в кодировку Latin-1(ISO-8859-1), сайт же отправляет данные с кодировкой windows-1251. Получалось что библиотека перекодировала данные сайта в другую кодировку.
Решил так:

sourse = requests.get('url')
sourse.encoding='windows-1251' # Теперь requests отдаёт данные в кодировке windows-1251 которая уже нормально читается

В принципе можно остаться на этой кодировке если при записи в файл указать encoding=’utf-8′
Ну если прям сильно хочется перекодировать в utf-8, можно раскодировать текст в utf-8 а потом закодировать в него

# if text is windows-1251
text = '123 asdasd 55f'
text = encode('utf-8').decode('utf-8')

Пригласить эксперта


  • Показать ещё
    Загружается…

09 окт. 2023, в 15:39

20000 руб./за проект

09 окт. 2023, в 15:37

35000 руб./за проект

09 окт. 2023, в 15:35

1000 руб./в час

Минуточку внимания

Recoder v3.1.0 (BOM-remover)

github

Небольшая программа для массового (пакетного) перекодирования файлов из одной кодировки в другую. Доступные кодировки windows-1251, koi8-r, cp866, ISO 8859-5, utf-8, utf-8 с BOM-заголовком. Также умеет искать и удалять BOM-заголовок в файлах и каталогах.

Текущая версия: ¶

  • Скачать recoder v3.1.0 для Windows 7+ 64-бит (9.7 MB)

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

  • Скачать recoder v3.1.0 для Ubuntu 20.04+ 64-бит (10.8 MB)

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

Некоторые антивирусы (например, VirusTotal) могут показывать наличие вирусов в исполняемом файле. Это связано с использованием PyInstaller и его модулей.
Если это является проблемой, то проект можно запускать из исходного кода или использовать версию v2.

Последнее изменение: ¶

  • 3 декабря 2022 г. — добавлена галочка «Искать в подкаталогах».
  • 5 марта 2022 г. — приложение переписано на Python (tkinter) с публикацией исходного кода.

Предыдущие версии: ¶

  • v3.0.0: Windows (9.7 MB), Linux (11 MB)
  • v2.3.0: Windows (7.9 MB), Linux (74 kB)
  • v2.2.2: Windows (7.9 MB), Linux (67.7 kB)
  • v2.2.1: Windows (7.9 MB), Linux (66.5 kB)
  • v2.1.1: Windows (7.2 MB), Linux (48.8 kB)
  • v2.1: Windows (8.2 MB), Linux (48.5 kB)
  • v2.0: Windows (7.9 MB)

Скриншоты ¶

Recoder 3.0.0

Recoder 3.0.0


Windows 10, Emacs 25.

When I want to convert file from Windows-1251 to UTF-8 I use Notepad++.

Before convert:

enter image description here

convert:

enter image description here

after convert:

enter image description here

My question is: Is it possible this convert in Emacs?

Braiam's user avatar

asked Aug 1, 2017 at 15:33

Alex's user avatar

One should use the command set-buffer-file-coding-system (C-x RET f), set the encoding, and then save the file.

Note that you may want to first revert-buffer-with-coding-system (C-x RET r) before performing the above step, if the file is opened with the wrong encoding in the first place.

answered Apr 11, 2018 at 12:54

xji's user avatar

xjixji

2,56518 silver badges36 bronze badges

1

The easiest way to do this is to:

  1. Type C-x RET c
  2. Select the desired coding system (in this case probably utf-8-dos)
  3. Pass C-x C-w as the command and pass the name of the file to write

answered Aug 1, 2017 at 15:37

3

This should do the trick:

  1. Visit the file with C-x C-f.
  2. Revert opened buffer to the original file encoding (cp-1251 in
    this case) with M-x + revert-buffer-wth-coding-system.
  3. Use M-x + set-buffer-file-coding-system to set encoding to utf-8.
  4. Save the file.

answered Dec 12, 2018 at 12:21

wotopul's user avatar

1

  • Главная
  • Новости
  • Web
    • PHP
    • JavaScript
    • HTML и CSS
    • MySQL
    • Apache
    • Домены
    • Заработок
    • SEO
    • Разное
  • ОС
    • FreeBSD
    • RouterOS
    • Windows
    • Linux
  • Утилиты
    • Git
    • Редакторы
  • Hardware
  • Микроконтроллеры Arduino
  • Справочники
    • Стандарты и справочники
    • Счета оплаты ЕСВ
  • Здоровье
  • Строительство и ремонт
  • Авто
  • Налогообложение
  • Разное
  • Веселые картинки
  • Whois доменов
  • Обратная связь

Главная / Web / PHP / Конвертация сайта из win-1251 …

Конвертация сайта из Windows-1251 в UTF-8

Забегая на перед можно с уверенностью сказать, что на сегодняшний день следует использовать исключительно кодировку UTF-8. Это, конечно, не означает, что нужно конвертировать из win-1251 в UTF-8 все, особенно не поддерживаемые более сайты, но задуматься о переводе активно развиваемых проектов нужно было еще, как говорят, вчера. Потребность в конвертации сайта из win-1251 в UTF-8 возникает по многим причинам, но для начала следует разобраться, в чем же принципиальная разница этих кодировок? Самое главное отличие — количество символов, которые могут содержаться в каждой из них.

Кодировка Windows-1251 может содержать не более 255 символов, так как все символы этой кодировки кодируются одним байтом. Из-за этой особенности, такие кодировки, как win-1251 еще называют «однобайтными». В состав Windows-1251 входят символы кириллического, латинского алфавитов, знаки препинания и некоторые другие символы. Из-за столь ограниченного набора символов, вывести в Windows 1251 символы китайского иероглифа (供) или, например, немецкого умляута (ö) невозможно.

Можно предположить, как делают множество создателей кириллических сайтов, что для проектов, на которых будут использоваться только кириллица или латинские символы кодировка utf-8 ни к чему. Еще больше, в приоритете использования Windows-1251 может убедить тот факт, что символы этой кодировки занимают меньше места, и в следствие чего немного быстрее обрабатываются строковыми функциями PHP.

Кодировка UTF-8 имеет настолько больше преимуществ, что увеличенный размер её символов перестает играть значимую роль и превращается в одни плюсы. В utf-8 хранится огромный набор знаков, иероглифов и букв различных алфавитов, включая и кириллические, в связи с чем русскоязычный сайт в кодировке utf-8 корректно отобразиться на компьютерах в Японии, арабских и других стран, которые даже не подозревают о существовании кодировки win-1251 и других однобайтных кодировок (KOI8-R, CP866, ISO 8859-5 и др.) с поддержкой кириллических символов.

Подробнее про кодировку UTF-8 можно узнать из материалов Википедии.

Перекодирование сайта в UTF-8

Перекодирование скриптов сайта из win-1251 в UTF-8 — это далеко не простое занятие, как может показаться на первый взгляд. Необходимо проделать большой объем работы, вкратце рассмотренный ниже:

  1. Конвертировать данные MySQL.
  2. Конвертировать файлы скриптов и некоторые другие.
  3. Заменить строковые функции на их мультибайтные аналоги.
  4. Изменить паттерны во многих функциях регулярных выражений.
  5. Заменить функции отправки почты.
  6. Исправить все внутренние перекодировки iconv() и др.
  7. Протестировать.

Большинство сложностей с конвертацией сайта из win-1251 (или любой другой однобайтовой кодировки) в UTF-8, в первую очередь вызваны тем, что PHP, даже самая новая версия (на момент написания статьи 5.4), не полностью поддерживает кодировку UTF-8. Поскольку большинство символов в UTF-8 закодированы двумя (до четырех) байт — обычные строковые функции не правильно работают с такими символами. Пример ниже следует набирать в UTF-8:

header(‘Content-type: text/html; charset=utf-8’);
$str = ‘Проверка кодировки’;
echo substr($str, 0, 7);

Вместо ожидаемого вывода «Проверк» получаем «Про» и «крокозябл» в конце — «�». Обычные строковые функции PHP предназначены для работы с однобайтными кодировками, символы которых состоят из одного байта, вот функция substr() и вырезает первые семь байт соответствующие симовлам «П,р,о» (кириллические буквы в UTF-8 кодируются 2-мя байтами) и первому байту буквы «в», вследствие чего «в» и превращается в «крокозябл �».

Далее будут рассмотрены способы, как подружить строковые функции PHP с кодировкой UTF-8.

Редактирование скриптов в кодировке UTF-8

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

В качестве редактора PHP-кода можно посоветовать бесплатный NetBeans или платные редакторы PhpStorm (99$), Zend Studio (299$). Поскольку это не обычные редакторы, а так называемые IDE (интегрированная среда разработки) — дополнительный функционал этих программ будет весьма кстати при рефакторинге кода для UTF-8.

Конвертация данных в MySQL

Перед конвертацией данных в базе MySQL из Windows-1251 в UTF-8 необходимо обязательно выполнить резервное копирование конвертируемой БД, в противном случае можно безвозвратно потерять все или часть данных! Следует обратить внимание, что в MySQL кодировка Windows-1251 называется cp1251, а UTF-8 — utf8.

Первым шагом необходимо обязательно проверить — соответствует ли кодировка БД, таблиц и всех её колонок соединению по умолчанию, во избежание необратимого перекодирования неизвестных новой кодировке символов в вопросительные знаки. Точнее, следует проверить, правильно ли «общался» скрипт с БД и нет ли во всех таблицах самой БД колонок с разными кодировками. Соединение с MySQL по умолчанию для всех запросов должно быть установлено в cp1251 — этот параметр задается либо в настройках MySQL в главном конфигурационном файле (MySQL — установка и настройка default-character-set=cp1251), либо в скриптах сайта сразу после подключения к БД: mysql_query(‘SET NAMES cp1251’). Для самой БД, таблиц и её колонок кодировка также, должна быть cp1251. Выполнить проверку поможет скрипт, код которого опубликован ниже (если таблиц не много можно посмотреть данные о кодировках при помощи PHPMyAdmin):

<?php
$mysqlhost = »;
$mysqlusers = »;
$mysqlpass = »;
$dbname = »;

$db = @mysql_connect($mysqlhost, $mysqlusers, $mysqlpass);
mysql_select_db($dbname);
//mysql_query(‘SET NAMES cp1251’);

// Скрипт проверки кодировок
// http://petrenco.com/php.php?txt=142

// Кодировка соединения
$result = mysql_query(‘show variables like «character_set_connection»;’);
$row = mysql_fetch_assoc($result);
$mysql_charset_conn = $row[‘Value’];

// Кодировка БД
$result = mysql_query(‘SHOW VARIABLES LIKE «character_set_database»;’);
$row = mysql_fetch_assoc($result);
$mysql_charset_db = $row[‘Value’];

$result = mysql_query(‘SHOW TABLES’);
while ($row = mysql_fetch_row($result))
  $tables_arr[] = $row[0];

$counter_tables = 0;
foreach ($tables_arr AS $table_name)
  {
  $result = mysql_query(‘SHOW CREATE TABLE  `’.$table_name.‘`’);
  while ($row = mysql_fetch_assoc($result))
    {
    preg_match_all(‘~\`(.*?)\` ([a-z]{1,10}).*?(?:character set|collate) ([a-z0-9-_]+) ~i’, $row[‘Create Table’], $matches);
    preg_match(‘~DEFAULT CHARSET\=([a-z0-9-_]+) {0,1}~i’, $row[‘Create Table’], $match);
    if (is_array($matches[1]))
      {
      foreach ($matches[0] as $key => $found_cols)
        {
        $res_arr[$table_name][‘columns’][$matches[1][$key]][‘type’] = $matches[2][$key];
        $res_arr[$table_name][‘columns’][$matches[1][$key]][‘charset’] = $matches[3][$key];
        }
      }
    if ($match[1] !== $mysql_charset_conn)
      {
      $res_arr[$table_name][‘default_charset’] = $match[1];
      }
    $counter_tables++;
    }
  }
//print_r($res_arr);

$table_txt = »;
foreach ($res_arr AS $table => $vals_arr)
  {
  if (is_array($vals_arr[‘columns’]))
    {
    foreach ($vals_arr[‘columns’] AS $column => $column_val)
      {
      $columns .= ‘<div style=»color: red; font-weight: bold;»>Колонка: ‘.$column.‘; тип: ‘.$column_val[‘type’].‘; кодировка: ‘.$column_val[‘charset’].‘</div>’;  
      }
    }
  else
    {
    $columns = ‘<span style=»color: green;»>Кодировка столбцов равна кодировке таблицы</span>’;
    }

   
  if (!empty($vals_arr[‘default_charset’]))  
    $default_charset_txt = ‘<span style=»color: red; font-weight: bold;»>’.$vals_arr[‘default_charset’].‘</span>’;
  else
    $default_charset_txt = ‘<span style=»color: green;»>’.$mysql_charset_conn.‘</span>’;
  $table_txt .=
      <tr style=»background: #fff;»>
        <td>’
.$table.‘</td>
        <td>’
.$default_charset_txt.‘</td>
        <td>’
.$columns.‘</td>
      </tr>’
;  
  }

 

if ($mysql_charset_db !== $mysql_charset_conn)
  $db_charset = ‘<h2 style=»color: red;»>В БД ‘.$dbname.‘ установлена кодировка по умолчанию: ‘.$mysql_charset_db.‘</h2>’;
else
  $db_charset = ‘<h2 style=»color: green;»>В БД ‘.$dbname.‘ установлена кодировка по умолчанию: ‘.$mysql_charset_db.‘</h2>’;

$counter_tables;

if (empty($table_txt))
  $table_found = ‘<h2 style=»color: green;»>Найдено таблиц ‘.$counter_tables.‘ шт., кодировка соединения соответствует табличным кодировкам по умолчанию</h2>’;
else
  {
  $table_found =
    <h2 style=»color: red;»>Таблицы не соответствующие кодировке соединения</h2>
    <table cellpadding=»5″ cellspacing=»1″ style=»background: grey;»>
      <tr style=»background: red;»>
        <th>Название таблицы</th>
        <th>Кодировка таблицы<br>
            (DEFAULT CHARSET)
        </th>
        <th>Кодировка колонок</th>
      </tr>
    ‘
.$table_txt.
    </table>’
;
  }

 
 
echo ‘<h1>Кодировка соединения с БД: <span style=»color: orange; font-size: 70px;»>’.$mysql_charset_conn.‘</span></h1>
    ‘
.$db_charset.
    ‘
.$table_found.»;
?>

Скрипт находит все несоответствующие соединению кодировки в БД. О наличии таких кодировок можно узнать из сообщений красного цвета. Как подготовить такие данные к конвертации можно прочитать тут: «Проблемы с кодировкой в MySQL версий 4.1+», «Исправление и преобразование кодировок таблиц MySQL». Если на странице только черный, зеленый и оранжевый (кодировка соединения) цвета — с кодировками в БД все впорядке и можно приступать к конвертированию данных: «Конвертация БД из Win-1251 в UTF8».

После преобразования данных в таблицах MySQL из cp1251 в utf8 необходимо изменить кодировку по умолчанию для скриптов (изменение настройки в my.ini / my.conf или SQL запросом SET NAMES utf8 каждый раз после подключения к БД). Также следует заменить заголовок с указанием кодировки, отправляемый сервером браузеру клиента. Это можно сделать изменив в HTML-коде строку, расположенную между дескрипторами <head>…</head>


<meta http-equiv=«Content-Type» content=«text/html; charset=UTF-8»>

или выведя заголовок непосредственно средствами PHP:

header(‘Content-type: text/html; charset=utf-8’);

Эти два способа указания кодировки браузеру можно совместить.

Теперь, вся информация из БД будет выводиться на страницах сайта как положено, а вот все тексты не латинскими буквами, расположенные в скриптах, отобразятся «кракозяблами». Для превращения «кракозяблов» в нормальный текст необходимо перекодировать уже сами скрипты, о чем речь пойдет в следующем разделе.

Перекодировка скриптов из Windows-1251 в UTF-8

Поскольку латинские буквы и знаки препинания имеют одинаковые коды символов как в кодировке Windows-1251 и так и в UTF-8 — проблем с их отображением не возникнет. В связи с этим ни код PHP, ни HTML-разметка, заданная латинскими буквами и знаками препинания практически не пострадают. Другое дело — кириллический алфавит.

Чтобы кириллические символы отображались как положено в кодировке UTF-8 необходимо их перекодировать. Один из простейших способов организовать этот процесс — использование мощностей библиотеки ICONV (PHP-функция iconv()). Конвертировать все подряд не нужно — необходимо исключить бинарные файлы (файлы изображений, pdf, архивов и др.) — если случайно конвертировать и их — данные этих файлов будут потеряны.

Скрипт, представленный ниже, помогает автоматизировать процесс конвертирования скриптов в UTF-8 из Windows 1251. Функция win1251_to_utf8() обрабатывает все вложенные директории и файлы, позволяя задать исключения — файлы и директории, данные в которых конвертировать в UTF-8 не нужно. Также необходимо задать расширения файлов — только файлы с заданными расширениями будут конвертированы. Перед запуском скрипта — обязательно сделайте резервную копию конвертируемых файлов! Ведь, например, если случайно запустить этот скрипт повторно, и конвертировать файлы, которые уже находятся в кодировке UTF-8 из Win1251 снова в UTF-8 — возможны проблемы с данными.

Перед запуском функции win1251_to_utf8(), следует ОБЯЗАТЕЛЬНО убедиться, что все файлы, подлежащие конвертации доступны на запись, в противном случае может получиться «каша» из файлов с кодировкой Windows-1251 и UTF-8, разобраться в которой будет уже совсем не легко. Для этих целей следует изначально задать переменной $convert значение 0. Если ошибок не найдено, то тогда нужно присвоить $convert значение 1.

<?php

ini_set(‘display_errors’, 1);

// Конвертер модуля ссылок

// Входные данные
// $source ……. — путь к директории, например my_script_w1251/scripts (в конце слеш не нужен)
// $ext_convert … — массив с разрешенными расширениями файлов — только файлы с указанными разрешениями будут конвертироваться. Например: array(‘php’, ‘inc’);
// $exclude …… — массив с файлами и директориями, данные которых конвертировать запрещено. Например: array(‘dir’ => array(‘mod’, ‘lib/scripts’), ‘file’ => array(‘lib/index.php’))
// $convert …… — флаг (1 перезаписывать файлы, 0 — только прочитать/проверить доступ на запись)
// $result ……. — стоит оставить пустым, используется для передачи данных при рекурсивном проходе директорий

// Результат выполнения — $result = win1251_to_utf8()
// $result[‘output_txt’] … — текстовый вывод в HTML результатов выполнения функции: черный цвет — найденный файл подлежит конвертации (расширение есть в массиве), серый цвет — не подлежит
function win1251_to_utf8($source, $ext_convert = array(), $exclude = array(‘file’ => array(), ‘dir’ => array()), $convert = 0, $result = array())
  {
  // http://petrenco.com/php.php?txt=142
  if (!isset($result[‘source’][‘dir’]))
    {
    $result[‘source’][‘dir’] = $source;
    $result[‘source’][‘strlen’] = mb_strlen($source);
    }
  if ($paths = array_diff(scandir($source), array(‘..’, ‘.’)))
    {
    foreach($paths as $path)
      {
      if (is_dir($source.‘/’.$path))
        {
        // Обработка исключений
        if (!in_array($source.‘/’.$path, $exclude[‘dir’]))
          {
          $result = win1251_to_utf8($source.‘/’.$path, $ext_convert, $exclude, $convert, $result);
          }
        }
      else
        {        
        if (!in_array($source.‘/’.$path, $exclude[‘file’]))
          {
          // Только файлы с определенными расширениями
          foreach ($ext_convert AS $key => $ext)
            $tmp .= ‘(?:\.’.$ext.‘)|’;
          $tmp = substr($tmp, 0, 1);
          $pattern = ‘~’.$tmp.‘$~i’;
          $result[‘counter_files’]++;
          if (preg_match($pattern, $source.‘/’.$path))
            {
            $file_content = file_get_contents($source.‘/’.$path);

            // Перекодировка
            $fs1 = filesize($source.‘/’.$path);
            if ($convert == 1)
              {
              // Проверка на доступность файла для записи
              if (!is_writable($source.‘/’.$path))
                {
                $result[‘output_txt’] .= ‘<div style=»color: red;»>’.$result[‘counter_files’].‘. Ошибка: ‘.$source.‘/’.$path.‘ не доступен для записи, конвертация остановлена.</div>’;
                return $result;
                }
              $file_content = iconv(‘windows-1251’, ‘utf-8’, $file_content);
              file_put_contents($source.‘/’.$path, $file_content);
              $fs2 = filesize($source.‘/’.$path);
              if ($fs1 != $fs2)
                $result[‘output_txt’] .= ‘<div style=»color: red;»>’.$result[‘counter_files’].‘. Ошибка: ‘.$source.‘/’.$path.‘ (‘.$fs1.‘ != ‘.$fs2.‘)</div>’;
              else
                $result[‘output_txt’] .= ‘<div style=»color: green;»>’.$result[‘counter_files’].‘. ‘.$source.‘/’.$path.‘</div>’;
              }
            else
              {
              if (!is_writable($source.‘/’.$path))
                $result[‘output_txt’] .= ‘<div style=»color: red;»>’.$result[‘counter_files’].‘. Ошибка: ‘.$source.‘/’.$path.‘ не доступен для записи.</div>’;
              else
                $result[‘output_txt’] .= ‘<div style=»»>’.$result[‘counter_files’].‘. ‘.$source.‘/’.$path.‘</div>’;
              }
            $result[‘path’][‘conv_file_path’][] = $source.‘/’.$path;
            }
          else
            {
            $result[‘output_txt’] .= ‘<div style=»color: #a0a0a0;»>’.$result[‘counter_files’].‘. ‘.$source.‘/’.$path.‘</div>’;
            }
          }
        }
      }
    }
  return $result;
  }

$source = ‘my_project/lib’; // Начинать с той же директории, из которой запущен файл с функцией
$convert = 0;
$ext_convert = array(‘php’, ‘inc’, ‘html’, ‘htm’);
$exclude_dir = array($source.‘/img’, $source.‘/scripts’); // Директории, файлы в которых конвертировать не нужно
$exclude_file = array($source.‘/!capcha.php’); // файлы, которые конвертировать не нужно
$exclude = array(‘file’ => $exclude_file, ‘dir’ => $exclude_dir);

$result_func = win1251_to_utf8($source, $ext_convert, $exclude, $convert);

echo ‘<html>

<head>
  <title>Конвертация файлов</title>
  <meta http-equiv=»Content-Type» content=»text/html; charset=utf-8″>
</head>

<body>

.$result_func[‘output_txt’].
</body>
</html>’
;

?>

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

setlocale (LC_ALL, «ru_RU.UTF-8»);

Эта строчка должна присутствовать вначале каждого скрипта.

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

Строковые функции PHP и UTF-8

Как было написано ранее, обычные строковые функции PHP (strlen(), substr(), strtolower() и др.) корректно работают только с однобайтными кодировками. Для мультибайтных кодировок, одной из которых и является UTF-8, необходимо применять специальные функции, например, из расширения PHP Mbstring.

Исключением является функция strlen(). В однобайтной кодировке, функция, возвращая количество символов, возвращает и размер строки в байтах, поскольку, как уже говорилось ранее, каждый символ в таких кодировках равен одному байту, и, соответственно, количество символов строки равно размеру в байтах. Заменять такую функцию, например на mb_strlen() нужно только тогда, когда задача strlen() была в подсчете количества символов. Если же strlen() использовалась для подсчета размера строки в байтах с последующей передачей этих данных, например в заголовок HTTP отправляемый клиенту для указания размера передаваемых данных — её следует оставить без изменений. Например, необходимо узнать размер и кол-во символов строки «строка, передаваемая клиенту»:

<?php

mb_internal_encoding(‘UTF-8’);
setlocale (LC_ALL, «ru_RU.UTF-8»);
header(‘Content-type: text/html; charset=utf-8’);

$str = ‘строка, передаваемая клиенту’;
$strlen = strlen($str);
$mb_strlen = mb_strlen($str);

echo ‘Строка состоит из: ‘.$strlen.‘ байт и ‘.$mb_strlen.‘ символов.’;
// 53 байта, 28 символов
?>

(В кодировке UTF-8 кириллические символы занимают 2 байта, пробел и запятая — 1 байт)

Есть несколько решений этой проблемы: перезагрузка функций, замена обычных строковых функций в коде на функции с приставкой «mb_» и использование функций написанных сторонними разработчиками или самостоятельно.

Перезагрузка функций

Перезагрузка функций — это указание интерпретатору PHP воспринимать часть обычных функций, работающих с однобайтовыми кодировками как функции MBString — со списком перегружаемых функций можно ознакомиться в официальной документации PHP). Чтобы выполнить перезагрузку функций необходимо в главном конфигурационном файле PHP (php.ini) установить параметр:

Ранее, до версии PHP 5.2.7, изменение настроек перезагрузки функций можно было осуществить в файле .htaccess (php_value mbstring.func_overload 2), но в более поздних версиях эта возможность, к сожалению, не доступна.

Если необходимо установить/отключить перезагрузку функций только для одного/нескольких сайтов следует воспользоваться директивой php_admin_value mbstring.func_overload 2 в конфигурации сервера Apache для виртуальных хостов.

Перезагрузку функций стоит применять лишь для быстрого изменения поведения скриптов. Мало того, что перезагрузка изменяет поведение далеко не всех необходимых функций, так еще она не решает проблему с определением, в каком контексте используется функция strlen().

Замена строковых функций

Замена строковых функций, другими словами рефакторинг кода PHP, более трудоёмкое, но и более правильное решение. Заменять обычные строковые функции можно на функции из библиотеки MBString или другие функции. Лучший вариант — заменить все однобайтовые функции аналогами с приставкой «mb_», а вот функции, которые аналогов не имеют (str_split(), wordwrap(), ucfirst(), lcfirst(), ucwords() и др.) — создавать самостоятельно или искать готовые решения в сети, например в комментариях к каждой из функций в официальной документации PHP.

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

Перед использованием функций из MBString необходимо установить внутреннюю кодировку скрипта в UTF-8 при помощи функции mb_internal_encoding(), которая должна выполнятся перед использованием всех функций MBString в скриптах

mb_internal_encoding(‘UTF-8’)

Также, задать внутреннюю кодировку скрипта можно в конфигурационном файле PHP — тогда этот параметр распространится на все скрипты.

Для начала следует создать проект в NetBeans, в который должны быть включены все скрипты, обслуживающие сайт. Далее, для замены, например функции substr(), необходимо создать собственную функцию substr() в новом файле подключенном к проекту, иначе рефакторинг произвести не удастся:

<?php
function substr() {};
?>

Потом на функции subst() нужно нажать правой кнопкой мыши и из меню выбрать: Refactor -> Rename, в поле New Name изменить subst на mb_substr и нажать кнопку «Preview»:

Теперь можно заменить все функции сразу во всех файлах проекта, либо предварительно просмотреть в каком контексте используется substr() в коде каждого файла скрипта — байты или символы.

На что еще следует обратить внимание

Регулярные выражения и UTF-8

Чтобы регулярные выражения в функциях preg_…() работали корректно, необходимо добавить модификатор шаблона u. Также, следует забыть о шаблоне \w, и заменить его на \pL, хотя лучше всего использовать такую конструкцию [а-я].

Функция iconv()

Необходимо найти все вызовы функций iconv() в коде скриптов сайта, и заменить кодировки, либо вообще убрать эту функцию там, где из UTF-8 символы перекодировались в Windows1251.

Sape

Если сайт работает с ситемой Сапе (на сайте размещаются ссылки), необходимо изменить код подключения Сапе и вместо $sape = new SAPE_client() нужно написать:

$o[‘charset’] = ‘UTF-8’;
$sape = new SAPE_client($o);
unset($o);

Подробнее тут.

Опубликовано: 2012/06/10

HTML-код ссылки на эту страницу:

<a href=»https://petrenco.com/php.php?txt=142″ target=»_blank»>Конвертация сайта из win-1251 в UTF-8</a>

53320

  • Как конвертировать диск из gpt в mbr при установке windows 10
  • Как конвертировать динамический диск в базовый в windows 10
  • Как корзину перенести с диска c на диск d в windows 10
  • Как конвертировать в mp3 в windows media player
  • Как копировать файлы с длинными именами в windows 7