Похожие вопросы:
Некоторые символы в CSV-файле не читаются во время PHP fgetcsv () ,
fgetcsv () игнорирует специальные символы, когда они находятся в начале строки
Мое приложение имеет форму, в которой пользователи могут загружать CSV-файл (его 5 внутренних пользователей всегда загружали действительный файл – с разделителями-запятыми, цитировали, заканчивали запись LF), а затем файл импортировался в базу данных с использованием PHP:
$fhandle = fopen($uploaded_file,'r'); while($row = fgetcsv($fhandle, 0, ',', '"', '\\')) { print_r($row); // further code not relevant as the data is already corrupt at this point }
По причинам, которые я не могу изменить, пользователи загружают файл, закодированный в кодировке Windows-1250
– однобайтную 8-разрядную кодировку символов.
Проблема: и некоторые (не все!) Символы за пределами 127 («расширенный ASCII») отбрасываются в fgetcsv()
. Пример данных:
"15","Ústav" "420","Špičák" "7","Tmaň"
становится
Array ( 0 => 15 1 => "stav" ) Array ( 0 => 420 1 => "pičák" ) Array ( 0 => 7 1 => "Tma" )
(Обратите внимание, что č
сохраняется, но Ú
удаляется)
В документации для fgetcsv говорится, что «поскольку 4.3.5 fgetcsv () теперь двоично-безопасный», но похоже, что это не так. Я что-то делаю неправильно, или эта функция сломана, и я должен искать другой способ разобрать CSV?
Оказывается, я недостаточно читал документацию – fgetcsv () только несколько двоично-безопасен. Это безопасно для простого ASCII <127, но в документации также говорится :
Заметка:
Эта функция учитывает настройку локали. Если LANG, например, en_US.UTF-8, файлы в однобайтовой кодировке считываются неправильно этой функцией
Другими словами, fgetcsv () пытается быть двоично-безопасным, но на самом деле это не так (потому что он одновременно возится с кодировкой), и, вероятно, он будет искажать данные, которые он читает (поскольку этот параметр не настроен в php .ini, а скорее читать из $LANG
).
Я обошел эту проблему, читая строки с помощью fgets
(которая работает на байтах, а не на символах) и использует функцию CSV из комментария в документах для их анализа в массив:
$fhandle = fopen($uploaded_file,'r'); while($raw_row = fgets($fhandle, 0)) { // fgets is actually binary safe $row = csvstring_to_array($raw_row, ',', '"', "\n"); // $row is now read correctly }