Я работаю над скриптом импорта csv в php. Он отлично работает, за исключением иностранных символов в начале поля.
Код выглядит так:
if (($handle = fopen($filename, "r")) !== FALSE) { while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) $teljing[] = $data; fclose($handle); }
Вот пример данных, показывающий мою проблему
føroyskir stavir, "Kr. 201,50" óvirkin ting, "Kr. 100,00"
Это приведет к следующему
array ( [0] => array ( [0] => 'føroyskir stavir', [1] => 'Kr. 201,50' ) [1] => array ( [0] => 'virkin ting', <--- Should be 'óvirkin ting' [1] => 'Kr. 100,00' ) )
Я видел, что этот behaivior документирован в некоторых комментариях в php.net, и я попробовал ini_set('auto_detect_line_endings',TRUE);
для обнаружения окончаний линии. Нет успеха.
Кто-нибудь знаком с этой проблемой?
Редактировать:
Спасибо вам, AJ, этот вопрос теперь решен.
setlocale(LC_ALL, 'en_US.UTF-8');
Было решение.
Из руководства PHP для fgetcsv()
:
«Примечание. Эта функция учитывается в настройках локали. Если LANG, например, en_US.UTF-8, файлы в однобайтовом кодировании неправильно считываются этой функцией».
Скопировано из комментариев PHP.net/fgetcsv:
kent at marketruler dot com 04-Feb-2010 11:18 Обратите внимание, что fgetcsv, по крайней мере, в PHP 5.3 или предыдущем, НЕ будет работать с кодированными UTF-16 файлами. Ваши параметры состоят в том, чтобы преобразовать весь файл в ISO-8859-1 (или latin1) или конвертировать строки за строкой и преобразовать каждую строку в кодировку ISO-8859-1, а затем использовать str_getcsv (или совместимую совместимость с обратной совместимостью). Если вам нужно читать нелатинские алфавиты, лучше всего конвертировать в UTF-8.
См. Str_getcsv для обратной совместимой версии его с PHP <5.3 и см. Utf8_decode для функции, написанной Rasmus Andersson, которая предоставляет utf16_decode. Добавленная модификация заключалась в том, что BOP появляется в верхней части файла, а не в последующих строках. Таким образом, вам нужно сохранить endian-ness, а затем повторно отправить его при каждом последующем расшифровке строки. Эта измененная версия возвращает endianness, если она недоступна:
<?php /** * Decode UTF-16 encoded strings. * * Can handle both BOM'ed data and un-BOM'ed data. * Assumes Big-Endian byte order if no BOM is available. * From: http://php.net/manual/en/function.utf8-decode.php * * @param string $str UTF-16 encoded data to decode. * @return string UTF-8 / ISO encoded data. * @access public * @version 0.1 / 2005-01-19 * @author Rasmus Andersson {@link http://rasmusandersson.se/} * @package Groupies */ function utf16_decode($str, &$be=null) { if (strlen($str) < 2) { return $str; } $c0 = ord($str{0}); $c1 = ord($str{1}); $start = 0; if ($c0 == 0xFE && $c1 == 0xFF) { $be = true; $start = 2; } else if ($c0 == 0xFF && $c1 == 0xFE) { $start = 2; $be = false; } if ($be === null) { $be = true; } $len = strlen($str); $newstr = ''; for ($i = $start; $i < $len; $i += 2) { if ($be) { $val = ord($str{$i}) << 4; $val += ord($str{$i+1}); } else { $val = ord($str{$i+1}) << 4; $val += ord($str{$i}); } $newstr .= ($val == 0x228) ? "\n" : chr($val); } return $newstr; } ?> Trying the "setlocale" trick did not work for me, eg <?php setlocale(LC_CTYPE, "en.UTF16"); $line = fgetcsv($file, ...) ?>
Но это, возможно, потому, что моя платформа не поддерживала его. Тем не менее, fgetcsv поддерживает только одиночные символы для разделителя и т. Д. И жалуется, что если вы передадите версию этого символа в UTF-16, я быстро сдался.
Надеюсь, это полезно кому-то там.