我正在开发一个必须读取大型CSV文件和处理数据的应用程序。绝对不可能在一个请求中进行,因为处理数据也需要时间,而不仅仅是阅读。
所以我到目前为止所尝试的内容以及迄今为止运作良好的内容如下:
// Open file
$handle = fopen($file, 'r');
// Move pointer to a place where it stopped last time
fseek($handle, $offset);
// Read limited line and process
for ($i = 0; $i < $limit; $i++) {
// Get length of line for offset purposes
$newlength = strlen(fgets($handle));
// Move pointer back. fgets moves pointer so we move it back for fgetcsv to get that line again
fseek($handle, $offset);
$line = fgetcsv($handle, 0, $csv_delimiter);
// Process data here
// Save offset
$offset += $newlength;
}
问题出现在这一行:
$newlength = strlen(fgets($handle));
当csv列有换行符时失败。
我也试过$newlength = strlen(implode(';', fgetcsv($handle, 0, $csv_delimiter)));
,但这并不总是有效。它通常会因为少数字符而失败。这里可能没有正确处理报价和行尾。
我只需要获得csv行的长度,而不仅仅是单行,而是csv行,它可能在引号内有换行符。
有人有更好的解决方案吗?
答案 0 :(得分:2)
做一件事,创建一个名为“my_csv_data”的mysql临时表,并在该表中添加一个字段,其中包含csv文件中的所有字段,并使用枚举(0,1)默认值'0添加一个“is_processed” ”。
现在导入该sql表中的所有csv数据。单次插入永远不会花费更多时间。
现在调用一个访问my_csv_data表10或100记录的函数/文件,其中is_processed ='0'并处理它,如果处理成功,则将“is_processed”字段更新为'1'。
现在创建一个命中该文件/函数的cronjob。周期性。
使用这种方式,数据将静默地插入到您的表中而不会打扰/遭受任何管理员/前端用户。
答案 1 :(得分:0)
我有codeignitor代码,我上传csv文件数据并将其插入mysql数据库。希望这会对你有所帮助
if($_FILES["file"]["size"] > 0)
{
$file = fopen($filename, "r");
while (($emapData = fgetcsv($file, 10000, ",")) !== FALSE)
{
$data = array(
'reedumption_code' => $emapData[0],
'jb_note_id' =>$jbmoney_id,
'jbmoney' =>$jbamount,
'add_date'=>time(),
'modify_date'=>time(),
'user_id'=>0,
'status'=>1,
'assign_date'=>0,
'del_status'=>1,
'store_status'=>1
);
$this->load->model('currency_model');
$insertId = $this->currency_model->insertCSV($data);
}
fclose($file);
redirect('currency/add_currency?msg=Data Imported Successfully');
}