Поврежденные данные с использованием UTF-8 и mb_substr

Я получаю данные из базы данных MySQL, поля varchar(255) utf8_general_ci и пытаюсь записать текст в PDF с помощью PHP. Мне нужно определить длину строки в PDF, чтобы ограничить вывод текста в таблице. Но я заметил, что вывод mb_substr/substr действительно странный.

Например:

mb_internal_encoding("UTF-8");

$_tmpStr = $vfrow['title'];
$_tmpStrLen = mb_strlen($vfrow['title']);
for($i=$_tmpStrLen; $i >= 0; $i--){
     file_put_contents('cutoffattributes.txt',$vfrow['field']." ".$_tmpStr."\n",FILE_APPEND);
     file_put_contents('cutoffattributes.txt',$vfrow['field']." ".mb_substr($_tmpStr, 0, $i)."\n",FILE_APPEND);
}

выводит это:

снимок экрана с npp

ссылка на файл npp

База данных:

введите здесь описание изображениявведите здесь описание изображения

Мой вопрос: откуда берется лишний персонаж?


person aLx13    schedule 22.04.2015    source источник
comment
Вы не предоставляете кодировку для mb_substr; вы уверены, что он получает правильную кодировку? См. также этот ответ.   -  person xathien    schedule 22.04.2015
comment
Вы используете mb_strlen()/mb_substr() вместо strlen()/substr(), потому что это может разрезать многобайтовый символ посередине, что правильно. Что могут сделать даже mb_strlen()/mb_substr(), так это разрезать составную последовательность посередине, например, n и ударение сверху. Вы можете избежать перекодирования содержимого в несоставную форму, которая существует для некоторых букв с диакритическими знаками.   -  person Ulrich Eckhardt    schedule 23.04.2015
comment
Можете ли вы показать нам вывод bin2hex ($_tmpStr) после установки переменной?   -  person Michas    schedule 24.04.2015
comment
@Michas bin2hex: 526f7a6d696172206369c499636961206b617761c5826b69207069657277737a792073746f706965c584   -  person aLx13    schedule 24.04.2015


Ответы (3)


  1. Вам необходимо убедиться, что вы действительно получаете данные из базы данных в кодировке UTF-8, установив соответствующую кодировку соединения. Это зависит от вашего адаптера базы данных, см. UTF-8 полностью для Детали.
  2. Вам нужно сообщить своим функциям mb_, что данные находятся в кодировке UTF-8, чтобы они могли правильно их обрабатывать. Либо установите это глобально для всех функций, использующих mb_internal_encoding, либо передайте параметр $encoding своей функции при ее вызове:

    mb_substr($_tmpStr, 0, $i, 'UTF-8')
    
person deceze♦    schedule 22.04.2015
comment
Я использовал mb_internal_encoding, но установка параметра кодировки mb_substr в UTF-8 сработала! - person aLx13; 23.04.2015

Дополнительный символ — это первая часть двухбайтовой последовательности UTF-8. У вас могут возникнуть проблемы с внутренней кодировкой многобайтовых строковых функций. Ваш код обрабатывает текст как фиксированную 1-байтовую кодировку. ń в UTF-8, шестнадцатеричный C5 84, обрабатывается как Ĺ„ в CP-1250 и Ĺ[IND]< /strong> в ISO-8859-2 два символа.

Попробуйте выполнить это поверх скрипта:

mb_internal_encoding("UTF-8");

http://php.net/manual/en/function.mb-internal-encoding.php

person Michas    schedule 22.04.2015
comment
Спасибо за указание, но я установил mb_internal_encoding в utf-8 - person aLx13; 23.04.2015

Помимо установки таблицы и поля в UTF-8, вам необходимо установить mysqli_set_charset('UTF -8') также в UTF-8 (если вы используете mysqli).

Вы тоже пробовали?

$_tmpStr = utf8_encode( $vfrow['title'] ); 
person Izzy    schedule 22.04.2015
comment
Я уже сделал это, поэтому я не понимаю этого поведения... SET NAMES utf8 & SET CHARACTER SET 'utf8' - person aLx13; 23.04.2015
comment
не могли бы вы улучшить свой вопрос с фактической структурой таблицы и небольшим количеством данных из нее? - person Izzy; 23.04.2015