Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 05.06.2013, 22:24
Аватар для Раед
''
Отправить личное сообщение для Раед Посмотреть профиль Найти все сообщения от Раед
 
Регистрация: 11.12.2011
Сообщений: 636

Почему строка "райд" состоит из 8 символов?
Выручайте!
Был сайт на php. Пхп файлы кодировались в Windows-1251, однако в базе данных (MySQL) стояла кодировка UTF-8. При работе с базой приходилось всё время кодировать строки туда-обратно. Решил перекодировать файлы на сервере в UTF-8.

На первый взгляд операция прошла удачно, но стоило мне авторизироваться на своём сайте, как я заметил проблему.
В одном месте ник выводится вертикально следующим образом: implode('<br>', str_split($halfName)). Так вот в этом месте вместо слова Райд пхп вертикально вывел мне в аккурат 8 неизвестных символов (FF отображает их в виде вопросиков).

Входе исследований с помощью FirePHP стало ясно, что длина строк (возвращаемая strlen), состоящих из русских символов, УДВАИВАЕТСЯ , а при применении к этим строкам любых функция (типа str_split или preg_replace) получается абракадабра.

Пожалуйста, помогите решить проблему
Ответить с цитированием
  #2 (permalink)  
Старый 06.06.2013, 18:49
Аватар для Раед
''
Отправить личное сообщение для Раед Посмотреть профиль Найти все сообщения от Раед
 
Регистрация: 11.12.2011
Сообщений: 636

Уже 33 просмотра и не одного ответа.
Это такая сложная проблема, такой глупый вопрос или такой длинный пост?
Ответить с цитированием
  #3 (permalink)  
Старый 06.06.2013, 20:04
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,586

Глупый и противный вопрос. Глупый, потому что UTF-8 - 8бит, 2 байта на символ в отличие от c1251, где 1 байт. Глюки связаны с этим. Противный потому что никому не охота разбираться где и в чём проблема конкретно у вас.
__________________
29375, 35
Ответить с цитированием
  #4 (permalink)  
Старый 06.06.2013, 20:25
Профессор
Отправить личное сообщение для oneguy Посмотреть профиль Найти все сообщения от oneguy
 
Регистрация: 31.05.2012
Сообщений: 396

В PHP исходный код представляется в однобайтовой кодировке, и также строки состоят только из символов в однобайтовой кодировке, или байтов.
Каждая буква русского алфавита в UTF-8 представляется двумя байтами, отсюда и данная проблема. Иными словами, strlen показывает количество байтов в строке, и все функции, работающие со строками, работают с отдельными байтами.
Я вижу 2 способа решить эту проблему.
1) Отправить строку на клиент как есть, а уже на клиенте с помощью Джаваскрипта расположить буквы вертикально.
2) Воспользоваться тем, что в UTF-8 первый байт последовательности байтов, представляющей один пункт Юникода, является в пределах 0 - 127 или 196 - 255, а остальные байты не являются. Поэтому на PHP можно написать собственную функцию, вставляющую "<br>" между пунктами Юникода, вместо implode.
Ответить с цитированием
  #5 (permalink)  
Старый 06.06.2013, 20:26
Аватар для Раед
''
Отправить личное сообщение для Раед Посмотреть профиль Найти все сообщения от Раед
 
Регистрация: 11.12.2011
Сообщений: 636

Сообщение от Aetae
Глупый, потому что UTF-8 - 8бит, 2 байта на символ
Вы уж определитесь, 8 бит или всё-таки 2 байта. Или вы считаете, что в байте 4 бита?
Ответить с цитированием
  #6 (permalink)  
Старый 06.06.2013, 20:29
Аватар для Раед
''
Отправить личное сообщение для Раед Посмотреть профиль Найти все сообщения от Раед
 
Регистрация: 11.12.2011
Сообщений: 636

oneguy,
Это всё конечно прекрасно, но не писать же для каждой строковой операции свою функцию. Не зря я наверно сделал бекап windows1251-сайта.
Просто даже не ожидал встретиться с такой проблемой, в Интернете читал статьи, где рекомендуют кодировать скрипты в UTF-8.
Ответить с цитированием
  #7 (permalink)  
Старый 06.06.2013, 20:42
Профессор
Отправить личное сообщение для oneguy Посмотреть профиль Найти все сообщения от oneguy
 
Регистрация: 31.05.2012
Сообщений: 396

Сообщение от Раед Посмотреть сообщение
oneguy,
Это всё конечно прекрасно, но не писать же для каждой строковой операции свою функцию. Не зря я наверно сделал бекап windows1251-сайта.
Ну а что же делать? Можно написать функии на PHP, переводящие строки из UTF-8 в CP1251 и обратно, и применять строковые операции к строкам в CP1251. Но можно использовать первый способ, описанный мной выше, мне кажется, что так делать легче и лучше в большинстве случаев.
Ответить с цитированием
  #8 (permalink)  
Старый 06.06.2013, 20:57
Аватар для Aetae
Тлен
Отправить личное сообщение для Aetae Посмотреть профиль Найти все сообщения от Aetae
 
Регистрация: 02.01.2010
Сообщений: 6,586

Сообщение от Раед Посмотреть сообщение
Вы уж определитесь, 8 бит или всё-таки 2 байта. Или вы считаете, что в байте 4 бита?
Да как обычно, упоролся, не обращай внимания. Utf-8 использует и 8(на ASCII) и 16 бит(на всё остальное).
Сообщение от Раед Посмотреть сообщение
oneguy,
Это всё конечно прекрасно, но не писать же для каждой строковой операции свою функцию.
Ну они вроде уж кем-то написаны, погуглите.
__________________
29375, 35
Ответить с цитированием
  #9 (permalink)  
Старый 06.06.2013, 20:59
Аватар для Раед
''
Отправить личное сообщение для Раед Посмотреть профиль Найти все сообщения от Раед
 
Регистрация: 11.12.2011
Сообщений: 636

Сообщение от oneguy
Можно написать функии на PHP, переводящие строки из UTF-8 в CP1251 и обратно, и применять строковые операции к строкам в CP1251
Да, была такая идея, и вот реализация.
function str_caller() {
  $args = func_get_args();
  $f = array_shift($args);
  $r = call_user_func_array($f, str_caller_encode($args));
  $r = str_caller_encode(array($r), true);
  return $r[0];
}
function str_caller_encode($args, $b=false) {
  foreach($args as $k => $v) {
    if (is_string($v)) {
      if ($b) $args[$k] = iconv('windows-1251', 'utf-8', $v);
      else $args[$k] = iconv('utf-8', 'windows-1251', $v);
    }
    if (is_array($v)) $args[$k] = str_caller_encode($v, $b);
  }
  return $args;
}

Вопрос, на сколько это безопасно. Вдруг какие-либо php-функции таки умеют работать с UTF-8 и неправильно переварят вызванный таким образом cp1251. Не хочется лишней путаницы.
Ответить с цитированием
  #10 (permalink)  
Старый 06.06.2013, 21:13
Аватар для Раед
''
Отправить личное сообщение для Раед Посмотреть профиль Найти все сообщения от Раед
 
Регистрация: 11.12.2011
Сообщений: 636

И вот ещё, для удобства
function create_utf_str_func($fs) {
  foreach ($fs as $v) {
    eval("
      if (!function_exists(utf_$v)) {
        function utf_$v() {
          \$args = func_get_args();
          array_unshift(\$args, '$v');
          return call_user_func_array('str_caller', \$args);
        }
      }
    ");
  }
}
//например:
create_utf_str_func(array('str_split'));
utf_str_split('some string с русскими буквами');

Вроде работает. Пока буду применять так.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Предполагается наличие ';' в IE7- FINoM (X)HTML/CSS 5 25.08.2012 16:05
Почему не удаляется строка? Shaienn Общие вопросы Javascript 1 05.02.2009 09:20