PHP實現(xiàn)導(dǎo)入大量CSV數(shù)據(jù)的示例代碼
前言
網(wǎng)上有很多介紹大量上傳數(shù)據(jù)的,感覺都是一個抄一個,這是自己寫的處理方式,在一些項目中已經(jīng)應(yīng)用.
主要利用 yield 完成文件讀取,這個重點看會了,其他基本就很簡單.
代碼部分
一. controller 寫法
//獲取請求的參數(shù) $arrayParams = Request::all(); $objCsvFile = $arrayParams['csv_file']; $strRealPath = $objCsvFile->getRealPath();//tmp路徑, 這里可以先保存到自己預(yù)定路徑,再進(jìn)行讀取 //**************重點在這一步********************// $glob = CommonUtilFunction::readPathCsvFile($strRealPath); //********************************************// $intRowNum = 0; while($glob->valid()) { $arrayNewLineData = []; $intRowNum++; if (1 === $intRowNum) { //第一行跳過,一般是標(biāo)題 $glob->next(); continue; } $arrayLineData = $glob->current(); //處理空字符串 空行 /** * 一般csv有兩種行數(shù)據(jù)可以被認(rèn)為是空行 * 第一種 ',,,,,,,,,,,,,,,,,,,,,,,,,,',類似這種純逗號沒有任何數(shù)據(jù) * 第二種 ' ',是真的空行,什么也沒有 * 處理完成返回一個統(tǒng)一的數(shù)組 [] */ $arrayLineData = CommonUtilFunction::dealCsvLineData($arrayLineData); //跳過空行 if (true === empty($arrayLineData)) { $glob->next(); continue; } //自己的代碼邏輯 ... // 避免意外錯誤 unset($arrayNewLineData); $glob->next(); // 處理下一行數(shù)據(jù) }
二. yield 讀取數(shù)據(jù)以及處理空行方法
/** * @description 迭代器讀取csv文件 * @param $strCsvPath * @return \Generator */ public static function readPathCsvFile($strCsvPath) { if ($handle = fopen($strCsvPath, 'r')) { while (!feof($handle)) { yield fgetcsv($handle); } fclose($handle); } } /** * @description 處理c單行信息 * @param $arrData * @return \Generator */public static function dealCsvLineData($arrData = []) { $arrAfterData = []; if (false === empty($arrData)) { //去除每個字符串 前后空格 foreach ($arrData as &$colData) { //檢測對應(yīng)編碼格式 csv文件格式Shift-JIS $strEncodeType = mb_detect_encoding($colData, ['UTF-8', 'Shift-JIS']); //如果認(rèn)為utf-8格式不用轉(zhuǎn)碼, shift-jis格式需要轉(zhuǎn)為utf8格式 if ('SJIS' === $strEncodeType) { //jis=>utf8 $colData = mb_convert_encoding($colData, 'UTF-8', 'Shift-JIS'); } $colData = trim($colData); } //去除空行 $isEmptyRow = true; foreach ($arrData as $item) { if ('' !== $item) { $isEmptyRow = false; break; } } if (false === $isEmptyRow) { $arrAfterData = $arrData; } } return $arrAfterData; }
結(jié)論
使用 yield 可以很大程度上減低服務(wù)器開銷,壓力在數(shù)據(jù)庫方面。上限沒有測試過,不過 1 萬條數(shù)據(jù)是很輕松.
知識點補充
yield是php5.6版本才有的函數(shù),作用是實現(xiàn)生成器,作用的在讀取文件的時候,可以一行一行的讀取
簡單的說可以理解為 php版本的非緩沖查詢,意思即是 把數(shù)據(jù)一行行 讀取到php運行內(nèi)存,并非一次性讀取到php運行內(nèi)存,眾所周知,php有很多內(nèi)置函數(shù),可以幫助我們對數(shù)據(jù)進(jìn)行加工操作,因為數(shù)據(jù)都在內(nèi)存里面,所以能操作,但是php的運行內(nèi)存是有極限,默認(rèn)128M。
以下附上php 實現(xiàn) yield 鏈接 mysql 幾種方法:
方法一
<?php $link = mysqli_connect('localhost','root','','advertising'); if( $result1 = mysqli_query($link, 'SELECT * FROM `test`',MYSQLI_USE_RESULT) ) { $result = $result1; // unset($result1); // mysqli_close($link); //如果這里切斷 mysql 鏈接 將無法獲取 數(shù)據(jù),原因是加了MYSQLI_USE_RESULT while ( $res = mysqli_fetch_assoc($result1) ){ echo $res['a'] . PHP_EOL; $i++; if( $i ==1000 ){ exit; } } } ?>
方法二
<?php $pdo = new \PDO('mysql:host=localhost;dbname=advertising','root',''); $pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); $res = $pdo->query("SELECT * FROM `test`"); //unset($pdo); $i = 0; if ($res) { while ($row = $res->fetch(PDO::FETCH_ASSOC)) { echo $row['a'] . PHP_EOL; $i++; if( $i ==1000 ){ exit; } } } ?>
方法三
<?php $mysqli = new mysqli("localhost", "root", "", "advertising"); $uresult = $mysqli->query("SELECT * FROM `test`", MYSQLI_USE_RESULT); //$uresult->close(); if ($uresult) { while ($row = $uresult->fetch()) { echo $row['a'] . PHP_EOL; $i++; if( $i ==1000 ){ exit; } } }
到此這篇關(guān)于PHP實現(xiàn)導(dǎo)入大量CSV數(shù)據(jù)的示例代碼的文章就介紹到這了,更多相關(guān)PHP導(dǎo)入CSV數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
php實現(xiàn)將普通數(shù)據(jù)轉(zhuǎn)化為json數(shù)據(jù)
在日常的開發(fā)工作中免不了要寫接口,json格式文本的輸出是制作接口必須掌握的,所以本文主要為大家詳細(xì)介紹了php如何將普通數(shù)據(jù)轉(zhuǎn)化為json數(shù)據(jù),需要的可以參考下2023-11-11PHP中foreach循環(huán)中使用引用要注意的地方
發(fā)現(xiàn)了一個容易出錯,但是不懂得原理卻解釋不明白的問題,碰到類似問題的朋友可以參考下。2011-01-01PHP設(shè)計模式之 策略模式Strategy詳解【對象行為型】
這篇文章主要介紹了PHP設(shè)計模式之 策略模式Strategy,結(jié)合實例形式詳細(xì)分析了PHP基于對象行為型的策略模式Strategy具體原理、實現(xiàn)技巧與相關(guān)操作注意事項,需要的朋友可以參考下2020-05-05詳解php 使用Callable Closure強制指定回調(diào)類型
這篇文章主要介紹了詳解php 使用Callable Closure強制指定回調(diào)類型的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下2017-10-10PHP echo,print,printf,sprintf函數(shù)之間的區(qū)別與用法詳解
這篇文章主要是對PHP中echo,print,printf,sprintf函數(shù)之間的區(qū)別與用法進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過來參考下,希望對大家有所幫助2013-11-11