PHP JSON_encode () получает «неправильно сформированные символы UTF-8, возможно, неправильно закодированные» (ошибка) - PullRequest
0 голосов
/ 30 мая 2018

Я не могу решить эту проблему, и я схожу с ума.

JSON_encode() генерирует ошибку: Malformed UTF-8 characters, possibly incorrectly encoded на нескольких записях (2 или 3) из набора записей по 10 тыс.Однако это кажется очень невозможным для исправления.

  • mysql уже есть utf8mb4 везде (база данных, таблица, столбцы и параметры сортировки)
  • php равен 7.2 и, конечно, в utf8
  • apache default charset is utf8 (однако ошибка - throw на уровне PHP).

Я также могу печатать для корректного отображения записи в PHP без проблем на простой странице отладки HTML.Однако, если я пытаюсь кодировать его в JSON, я получаю сообщение об ошибке.

Я обнаружил, что эти записи были импортированы из CVS, возможно, в обход очистителя.Странно то, что весь CSV-файл анализируется с помощью:

$this->encoding = mb_detect_encoding($source,mb_detect_order(),true);
if ($this->encoding!="" && $this->encoding!="UTF8") {
    $source = iconv($this->encoding, "UTF-8", $source);
} 

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

RESIDENCE �PRINCIPE

ОБНОВЛЕНИЯ

Я пытаюсь получить битовый код этих сломанных символов.Это то, что я нашел.В ASCII с использованием простой встроенной функции str_split и ord эти символы:

'�' 160

Я хотел бы найти битовый код также в utf8, поэтому я нахожу эту полезную функцию на PHP.net http://php.net/manual/en/function.ord.php#109812 которые пытаются найти битовый код MultiByteStrings.и это дает мне:

-2096

Что ....... отрицательно?

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

решено!

Проблема была в функции mb_detect_order(), эта функция просто не работает, как я ожидал.Я думал, что это список полного порядка поддержки кодирования, который в основном используется для ускорения процесса обнаружения.

Но я только что обнаружил, что эта функция возвращает только 2 кодировки:

//print_r(mb_detect_order());
Array
(
    [0] => ASCII
    [1] => UTF-8
)

Что практически совершенно бесполезно в моем случае.Функции MB могут обнаружить намного больше кодировки.Вы можете проверить их, запустив mb_list_encodings() и получить полный список:

//print_r(mb_list_encodings());
Array
(
    [0] => pass
    [1] => auto
    [2] => wchar
    [3] => byte2be
    [4] => byte2le
    [5] => byte4be
    [6] => byte4le
    [7] => BASE64
    [8] => UUENCODE
    [9] => HTML-ENTITIES
    [10] => Quoted-Printable
    [11] => 7bit
    [12] => 8bit
    [13] => UCS-4
    [14] => UCS-4BE
    [15] => UCS-4LE
    [16] => UCS-2
    [17] => UCS-2BE
    [18] => UCS-2LE
    [19] => UTF-32
    [20] => UTF-32BE
    [21] => UTF-32LE
    [22] => UTF-16
    [23] => UTF-16BE
    [24] => UTF-16LE
    [25] => UTF-8
    [26] => UTF-7
    [27] => UTF7-IMAP
    [28] => ASCII
    [29] => EUC-JP
    [30] => SJIS
    [31] => eucJP-win
    [32] => EUC-JP-2004
    [33] => SJIS-win
    [34] => SJIS-Mobile#DOCOMO
    [35] => SJIS-Mobile#KDDI
    [36] => SJIS-Mobile#SOFTBANK
    [37] => SJIS-mac
    [38] => SJIS-2004
    [39] => UTF-8-Mobile#DOCOMO
    [40] => UTF-8-Mobile#KDDI-A
    [41] => UTF-8-Mobile#KDDI-B
    [42] => UTF-8-Mobile#SOFTBANK
    [43] => CP932
    [44] => CP51932
    [45] => JIS
    [46] => ISO-2022-JP
    [47] => ISO-2022-JP-MS
    [48] => GB18030
    [49] => Windows-1252
    [50] => Windows-1254
    [51] => ISO-8859-1
    [52] => ISO-8859-2
    [53] => ISO-8859-3
    [54] => ISO-8859-4
    [55] => ISO-8859-5
    [56] => ISO-8859-6
    [57] => ISO-8859-7
    [58] => ISO-8859-8
    [59] => ISO-8859-9
    [60] => ISO-8859-10
    [61] => ISO-8859-13
    [62] => ISO-8859-14
    [63] => ISO-8859-15
    [64] => ISO-8859-16
    [65] => EUC-CN
    [66] => CP936
    [67] => HZ
    [68] => EUC-TW
    [69] => BIG-5
    [70] => CP950
    [71] => EUC-KR
    [72] => UHC
    [73] => ISO-2022-KR
    [74] => Windows-1251
    [75] => CP866
    [76] => KOI8-R
    [77] => KOI8-U
    [78] => ArmSCII-8
    [79] => CP850
    [80] => JIS-ms
    [81] => ISO-2022-JP-2004
    [82] => ISO-2022-JP-MOBILE#KDDI
    [83] => CP50220
    [84] => CP50220raw
    [85] => CP50221
    [86] => CP50222
)

Я ошибся, думая, что mb_detect_order была просто упорядоченной версией этого списка.mb_detect_order просто ... бесполезен.Для правильного кодирования в UTF8 используйте следующий код:

$my_encoding_list = [
    "UTF-8",
    "UTF-7",
    "UTF-16",
    "UTF-32",
    "ISO-8859-16",
    "ISO-8859-15",
    "ISO-8859-10",
    "ISO-8859-1",
    "Windows-1254",
    "Windows-1252",
    "Windows-1251",
    "ASCII",
    //add yours preferred
];

//remove unsupported encodings
$encoding_list = array_intersect($my_encoding_list, mb_list_encodings());

//detect 'finally' the encoding
$this->encoding = mb_detect_encoding($source,$encoding_list,true);

Это сработало и решило мою проблему с неверными данными, сохраненными в базе данных.

0 голосов
/ 31 мая 2018

Вы можете отфильтровать эти неизвестные символы, используя кодировку UTF-8//IGNORE в вашем методе iconv.

$this->encoding = mb_detect_encoding($source,mb_detect_order(),true);

if ($this->encoding!="" && $this->encoding!="UTF8") {
    $source = iconv($this->encoding, "UTF-8//IGNORE", $source);
} 

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...