Мне приходится сталкиваться с проблемой чтения символов Unicode из CSV-файла с помощью PHP.
Ниже приведен скриншот файла ccv UNICODE.
Код PHP, который я использую, приведен ниже.
$delimiter = ","; $row = 1; $handle = fopen($filePath, "r"); while (($data = fgetcsv($handle, 1000, $delimiter)) !== FALSE) { $num = count($data); $row++; for ($c=0; $c < $num; $c++) { echo $data[$c]; } } fclose($handle);
Для приведенного выше кода я получаю снизу как вывод в браузере Chrome. У него есть ненужные символы.
Но если я добавлю символ новой строки в оператор эха, как показано ниже, он даст правильный результат.
echo $data[$c]."\n";
Почему он ведет себя так? Я не хочу добавлять новую строку вроде этого.
UNICODE csv-файл.
Кодировка, которую Windows вызывает «Unicode» (ошибочно, Unicode не является кодировкой) на самом деле является UTF-16LE. Это кодировка с двумя байтами на код, поэтому символы ASCII выходят в виде байта ASCII, за которым следует нулевой байт.
Функция fgetcsv
PHP не поддерживает CSV UTF-16, она поддерживает только кодировки, совместимые с ASCII. Он разбивается на каждый байт 0x0A (новая строка) и 0x2C (запятая), но в UTF-16LE и новая строка и запятая являются двухбайтными последовательностями, 0x0A 0x00 и 0x2C 0x00 соответственно. Это означает, что вы получаете ведущие одиночные 0x00 байт в передней части каждого поля, но первый, и вы получаете неправильное разделение, когда значение содержит байты 0x0A или 0x2C, которые не являются частью новой строки / запятой UTF-16.
Когда вы печатаете это на выходе с кодировкой UTF-16LE, дополнительный 0x00 байт помещает каждое поле из двухбайтового выравнивания с последним, что означает, что просмотр в браузере видит переменные поля как несогласованные и печатает бессмысленные символы состоящий из младшего байта одного символа с байтом следа того, который был перед ним.
Таким образом, вы можете сделать две вещи:
если у вас есть выбор в этом вопросе, избегайте UTF-16. Поскольку он не совместим с ASCII, он разбивает множество инструментов, которые ожидают этого. Как правило, лучшим кодированием является UTF-8, который может включать в себя все символы и по-прежнему быть ASCII-надмножеством … к сожалению, Excel отказывается сохранять CSV-файлы непосредственно в UTF-8.
используйте другой синтаксический анализатор CSV, который понимает UTF-16. Это хорошая идея, чтобы избежать CSV-функций PHP в любом случае, потому что они делают странные вещи, которые не соответствуют стандартным CSV (в той мере, в какой существует стандарт … по крайней мере, это не соответствует RFC 4180 и тому, что производит Excel).
Попробуйте добавить это, прежде чем показывать текст
header('Content-Type: text/html; charset=utf-8'); $delimiter = ","; $row = 1; $handle = fopen($filePath, "r"); while (($data = fgetcsv($handle, 1000, $delimiter)) !== FALSE) { $num = count($data); $row++; for ($c=0; $c < $num; $c++) { echo $data[$c]; } } fclose($handle);