???? при сохранении в БД из выгруженного файла

fedukonelove

Беда. Бьюсь целый день и перепробовал уже возможно все варианты.

Имеется выгружаемый архив, который разархивируется классом ZipArchive, и дальше открываются файлы из архива и перебираются через foreach строки из этого файла. Есть в этом архиве файл со строками на кириллице (некоторые, не все), и когда я сохраняю эти строки в бд, то у меня сохраняются вместе кириллицы знаки вопросов или вообще пустые строки, если я пытаюсь их перекодировать. Латиница же сохраняется хорошо в то же время.

Как задать нужную кодировку при выгрузке из ZipArchive я способа не нашел, видимо его нет совсем.

Эти строки двух кодировок — либо ANCI, либо UTF-8. Странно что и бд UTF-8, что и настройки в скрипте Charset — тоже UTF-8. Даже пытался менять на utf8mb4, но все так же безуспешно.

При переборе строк я разными способами пытался менять кодировки. Один из способов:

Код (Text):
  1. iconv(mb_detect_encoding($value), «UTF-8», $value)

Но снова замечу, что я не знаю какую кодировку уже выставлять! То ли UTF-8, то ли CP-1251.. Всё это не работает.

Фреймворк Yii2. Mysql и php 7.4

Но я все таки грешу на файлы из этого архива, потому что ниже из кода если я перекоментирую NAME на другой NAME где написано мной, то все успешно сохраняется.

Нужно как то работать с данными из этого файла.

Вот кусок кода:

Код (Text):
  1.         foreach (explode(«n», $zip->getFromName(«bm_date.dat»)) as $value) {
  2.  
  3.             $entry = explode(«;», $value);
  4.  
  5.             $array[] = [
  6.                 ‘ID’ => $entry[0],
  7.               ‘NAME’ => $entry[1],
  8. //                 ‘NAME’ => ‘тест’
  9.             ];
  10.         }
  11.  
  12.   // здесь я выбрал рандомную запись из созданного массива, которая на кириллице
  13.         $ttest = new Tabletest();
  14.         $ttest->ID = $array[8][‘ID’];
  15.         $ttest->NAME = $array[8][‘NAME’];
  16.         $ttest->save();
 

Drunkenmunky

https://www.php.net/manual/ru/mysqli.set-charset

 

fedukonelove

Я ведь писал, что и charset тоже менял. Вот что в файле config/db.php

Код (Text):
  1. <?php
  2.  
  3. return [
  4.     ‘class’ => ‘yiidbConnection’,
  5.     ‘dsn’ => ‘mysql:host=localhost;dbname=****’,
  6.     ‘username’ => ‘****’,
  7.     ‘password’ => ‘****’,
  8.     ‘charset’ => ‘utf8mb4’,
  9.  
  10.     // Schema cache options (for production environment)
  11.     //’enableSchemaCache’ => true,
  12.     //’schemaCacheDuration’ => 60,
  13.     //’schemaCache’ => ‘cache’,
  14. ];
 

Drunkenmunky

Исправьте на utf8
Убедитесь, что распаковываемый текстовый файл в этой же кодировке(utf-8 для iconv, utf8 для mysql).

Кроме того, попробуйте передать кодировку в элементе

Код (Text):
  1. ‘dsn’ => ‘mysql:host=localhost;dbname=****’,

как

Код (Text):
  1. ‘dsn’ => ‘mysql:host=localhost;dbname=****’;charset=utf8,
 

fedukonelove

Я выставлял и utf-8. И я никак не могу повлиять кодировку загружаемого архива и файлов в нём — это устанавливает сайт из которого я выгружаю. Так что я понимаю что проблема может быть в этих файлах, но не могу найти как поменять мне при загрузке кодировку этих файлав

 

Drunkenmunky

Только перекодировать.
Если нет специального маркера(ВОМ) в начале файла в многобайтной кодировке, mb_detect бесполезен.

 

fedukonelove

Как перекодировать?

 

Drunkenmunky

Ну, вы же используете iconv() в своем коде.
Вероятно знакомы с его описанием

PHP:
  1. $str = iconv(‘cp1251’, «UTF-8//IGNORE», $str);
 

fedukonelove

Можете посмотреть архив. Проблемный файл bm_exch.dat

Ссылка http://api.bestchange.ru/info.zip

 

Drunkenmunky

Обычный CSV в cp1251
Возможен, конечно, вариант, что там встречаются строки, как 1251, так и в utf-8.
В этом случае, это просто мусор.

 

Drunkenmunky

fedukonelove

Не могли бы краткий пример привести? Я уже не в силах такого масштаба статьи читать

 

Drunkenmunky

Код (Text):
  1. LOAD DATA LOCAL INFILE
  2. ‘/path/to/file.csv’
  3. INTO TABLE `tablename`
  4. CHARACTER SET ‘cp1251’
  5. FIELDS TERMINATED BY ‘;’ ENCLOSED BY ‘»‘
  6. LINES TERMINATED BY ‘rn’

Количество колонок в таблице должно соответствовать.

 

fedukonelove

Спасибо. Буду пробовать

 

fedukonelove

В общем разобрал один метод из гитхаба с парсингом этим же.. Посмотрел как он раскодировал и нашел рабочий способ:
Вставить перекодирование всей строки в начале цикла

Код (Text):
  1.         foreach (explode(«n», $zip->getFromName(«bm_date.dat»)) as $value) {
  2.          
  3.             $value = iconv(‘CP1251’, ‘UTF-8’, $value);  // ЭТА СТРОКА
  4.  
  5.             $entry = explode(«;», $value);
  6.             $array[] = [
  7.                 ‘ID’ => $entry[0],
  8.               ‘NAME’ => $entry[1],
  9. //                 ‘NAME’ => ‘тест’
  10.             ];
  11.         }

Как ни странно проблема решилась — все строки теперь добавляются в бд корректно. Вроде бы я пробовал перекодировать целую строку, но возможно не попадал с самими кодировками..

Drunkenmunky всё же спасибо за помощь

 

MouseZver

php8guru

Так вам этот способ и советовали изначально. делать iconv на каждую строку.

 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *