用 editplus 打开 csv 格式的文件,会发现编码为 ANSI。在 ANSI 里,GBK 是专门来解决中文编码的,是双字节的,不论中英文都是双字节。通常程序保存文件的编码常为 UTF-8,因此读取 csv 文件时,需要进行编码转换,把 GBK 的转为 UTF-8,导出的时候再把 UTF-8 转换为 GBK。
csv 格式的文件
标题,日期
测试1,2020-10-29
处理代码
<?php
function utf8ToAnsi($str)
{
return iconv('UTF-8', 'GBK//ignore', $str);
}
function ansiToUtf8($str)
{
$encode = mb_detect_encoding($str, array('ASCII', 'UTF-8', 'GB2312', 'GBK', 'BIG5'));
if ('UTF-8' != $encode) {
return iconv($encode, 'UTF-8//IGNORE', $str);
}
return $str;
}
function exportCsv($title, array $header, array $data)
{
set_time_limit(0);
$filename = utf8ToAnsi($title, 1);
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="' . $filename . '"');
header('Cache-Control: max-age=0');
$fp = fopen('php://output', 'a');
$print_hea = array_map('utf8ToAnsi', $header);
fputcsv($fp, $print_hea);
foreach ($data as $value) {
fputcsv($fp, array_map('utf8ToAnsi', $value));
}
fclose($fp);
exit;
}
$file = fopen(utf8ToAnsi('导入.csv'),'r');
$result = [];
while ($data = fgetcsv($file)) {
$result[] = array_map('ansiToUtf8', $data);
}
$fileName = '导出.csv';
$header = array('标题', '日期', '新增项');
$cnt = 0;
$data = [];
foreach ($result as $array) {
if ($cnt ++ == 0) {
continue;
}
$tem = [];
$tmp[] = $array[0];
$tmp[] = $array[1];
$tmp[] = 'new';
$data[] = $tmp;
}
exportCsv($fileName, $header, $data);
认真看过代码后,会觉得中间那个编码转换的步骤是多此一举,这里可以这么说,但用到项目里就不一样了,项目里可能是读取 csv 文件校验然后入库,再从库里取出数据再导到 csv 文件里,这时就不是多此一举了,而是必须的了,因为数据库里为 UTF8 编码的,没经过转换会乱码的。