fedukonelove
Беда. Бьюсь целый день и перепробовал уже возможно все варианты.
Имеется выгружаемый архив, который разархивируется классом ZipArchive, и дальше открываются файлы из архива и перебираются через foreach строки из этого файла. Есть в этом архиве файл со строками на кириллице (некоторые, не все), и когда я сохраняю эти строки в бд, то у меня сохраняются вместе кириллицы знаки вопросов или вообще пустые строки, если я пытаюсь их перекодировать. Латиница же сохраняется хорошо в то же время.
Как задать нужную кодировку при выгрузке из ZipArchive я способа не нашел, видимо его нет совсем.
Эти строки двух кодировок — либо ANCI, либо UTF-8. Странно что и бд UTF-8, что и настройки в скрипте Charset — тоже UTF-8. Даже пытался менять на utf8mb4, но все так же безуспешно.
При переборе строк я разными способами пытался менять кодировки. Один из способов:
Код (Text):
iconv(mb_detect_encoding($value), «UTF-8», $value)Но снова замечу, что я не знаю какую кодировку уже выставлять! То ли UTF-8, то ли CP-1251.. Всё это не работает.
Фреймворк Yii2. Mysql и php 7.4
Но я все таки грешу на файлы из этого архива, потому что ниже из кода если я перекоментирую NAME на другой NAME где написано мной, то все успешно сохраняется.
Нужно как то работать с данными из этого файла.
Вот кусок кода:
Код (Text):
foreach (explode(«n», $zip->getFromName(«bm_date.dat»)) as $value) { $entry = explode(«;», $value); $array[] = [ ‘ID’ => $entry[0], ‘NAME’ => $entry[1], // ‘NAME’ => ‘тест’ ]; } // здесь я выбрал рандомную запись из созданного массива, которая на кириллице $ttest = new Tabletest(); $ttest->ID = $array[8][‘ID’]; $ttest->NAME = $array[8][‘NAME’]; $ttest->save();
Drunkenmunky
https://www.php.net/manual/ru/mysqli.set-charset
fedukonelove
Я ведь писал, что и charset тоже менял. Вот что в файле config/db.php
Код (Text):
<?php return [ ‘class’ => ‘yiidbConnection’, ‘dsn’ => ‘mysql:host=localhost;dbname=****’, ‘username’ => ‘****’, ‘password’ => ‘****’, ‘charset’ => ‘utf8mb4’, // Schema cache options (for production environment) //’enableSchemaCache’ => true, //’schemaCacheDuration’ => 60, //’schemaCache’ => ‘cache’, ];
Drunkenmunky
Исправьте на utf8
Убедитесь, что распаковываемый текстовый файл в этой же кодировке(utf-8 для iconv, utf8 для mysql).Кроме того, попробуйте передать кодировку в элементе
Код (Text):
‘dsn’ => ‘mysql:host=localhost;dbname=****’,как
Код (Text):
‘dsn’ => ‘mysql:host=localhost;dbname=****’;charset=utf8,
fedukonelove
Я выставлял и utf-8. И я никак не могу повлиять кодировку загружаемого архива и файлов в нём — это устанавливает сайт из которого я выгружаю. Так что я понимаю что проблема может быть в этих файлах, но не могу найти как поменять мне при загрузке кодировку этих файлав
Drunkenmunky
Только перекодировать.
Если нет специального маркера(ВОМ) в начале файла в многобайтной кодировке, mb_detect бесполезен.
fedukonelove
Как перекодировать?
Drunkenmunky
Ну, вы же используете iconv() в своем коде.
Вероятно знакомы с его описаниемPHP:
fedukonelove
Можете посмотреть архив. Проблемный файл bm_exch.dat
Ссылка http://api.bestchange.ru/info.zip
Drunkenmunky
Обычный CSV в cp1251
Возможен, конечно, вариант, что там встречаются строки, как 1251, так и в utf-8.
В этом случае, это просто мусор.
Drunkenmunky
В связи со вскрывшимися обстоятельствами, вы можете использовать
https://dev.mysql.com/doc/refman/5.6/en/load-data.html
Ничего перекодировать не придется.
fedukonelove
Не могли бы краткий пример привести? Я уже не в силах такого масштаба статьи читать
Drunkenmunky
Код (Text):
LOAD DATA LOCAL INFILE ‘/path/to/file.csv’ INTO TABLE `tablename` CHARACTER SET ‘cp1251’ FIELDS TERMINATED BY ‘;’ ENCLOSED BY ‘»‘ LINES TERMINATED BY ‘rn’Количество колонок в таблице должно соответствовать.
fedukonelove
Спасибо. Буду пробовать
fedukonelove
В общем разобрал один метод из гитхаба с парсингом этим же.. Посмотрел как он раскодировал и нашел рабочий способ:
Вставить перекодирование всей строки в начале циклаКод (Text):
foreach (explode(«n», $zip->getFromName(«bm_date.dat»)) as $value) { $value = iconv(‘CP1251’, ‘UTF-8’, $value); // ЭТА СТРОКА $entry = explode(«;», $value); $array[] = [ ‘ID’ => $entry[0], ‘NAME’ => $entry[1], // ‘NAME’ => ‘тест’ ]; }Как ни странно проблема решилась — все строки теперь добавляются в бд корректно. Вроде бы я пробовал перекодировать целую строку, но возможно не попадал с самими кодировками..
Drunkenmunky всё же спасибо за помощь
MouseZver
PHP:
php8guru
Так вам этот способ и советовали изначально. делать iconv на каждую строку.