我是Lem0擎淤,自學(xué)倡導(dǎo)者奢啥,執(zhí)迷于“不務(wù)正業(yè)”,被批評(píng)“旁門左道”嘴拢。我注冊(cè)并使用簡(jiǎn)書桩盲,希望能夠記錄一些我記不住的事情,或者與大家一起共享知識(shí)席吴,共同學(xué)習(xí)赌结。
從導(dǎo)師那里接到這個(gè)項(xiàng)目的時(shí)候,我還認(rèn)為DBase數(shù)據(jù)庫(kù)已經(jīng)從這個(gè)世界上消失了孝冒,沒有一家公司和企業(yè)依然在使用DBF文件存儲(chǔ)數(shù)據(jù)柬姚。然而我想錯(cuò)了,我國(guó)教育部門依然在使用這種格式的文件庄涡,無論是我手中合法獲取的數(shù)據(jù)量承,還是其他部門人員透露的消息,DBF數(shù)據(jù)文件確實(shí)從學(xué)生高考入學(xué)到畢業(yè)時(shí)填寫去向表都一直存在著穴店,并且在短時(shí)間內(nèi)撕捍,教育系統(tǒng)中不會(huì)有其他來代替DBase數(shù)據(jù)庫(kù)。
基于這種情況泣洞,這個(gè)數(shù)據(jù)可視化項(xiàng)目可以概括為提取我手中DBF文件里的100萬條數(shù)據(jù)并加以處理忧风,繪制統(tǒng)計(jì)圖表。
PHP的DBase擴(kuò)展
我是用的后端語言是PHP斜棚,開發(fā)環(huán)境是Windows8+wamp阀蒂。為了讓PHP能夠處理DBF文件,我需要下載安裝一個(gè)名為php_dbase.dll的擴(kuò)展庫(kù)弟蚀。
我搜遍全網(wǎng),發(fā)現(xiàn)PHP5.3時(shí)期已經(jīng)完全棄用dbase擴(kuò)展和相關(guān)函數(shù)的使用酗失。我的wamp搭載的是PHP5.5义钉,自然不能使用php_dbase.dll了。
后來我在PHP官網(wǎng)上搜索规肴,得到PHP7.0支持dbase數(shù)據(jù)庫(kù)擴(kuò)展的消息捶闸。我快速下載了最新版本的wamp夜畴,支持PHP5和PHP7的相互轉(zhuǎn)換。之后我使用PHP7.0.10成功地載入了php_dbase.dll删壮。
處理DBF文件
我在PHP手冊(cè)中查得操作DBF文件的多個(gè)函數(shù)贪绘,功能簡(jiǎn)單但足夠我使用。
//打開數(shù)據(jù)庫(kù)央碟,其中第二參數(shù)為打開方式:
0-只讀税灌;1-只寫;2-可讀寫
dbase_open($filename, $mode)
//關(guān)閉數(shù)據(jù)庫(kù)
dbase_close($identifier)
//讀取一條記錄亿虽,返回一個(gè)關(guān)系型數(shù)組
dbase_get_record_with_names($identifier, $index)
//獲取數(shù)據(jù)庫(kù)中數(shù)據(jù)總條數(shù)
dbase_numrecords($identifier)
首先我使用一個(gè)循環(huán)菱涤,讀取每一條數(shù)據(jù)并進(jìn)行處理:
for ($i = 0; $i < $dbase_numrecord($db); $i++) {
$row = dbase_get_record_with_names($db, $i);
//...其他處理
}
寫成整個(gè)程序之后我發(fā)現(xiàn),由于PHP本身的效率問題洛勉,加之?dāng)?shù)據(jù)量龐大(100萬條數(shù)據(jù))粘秆,我的瀏覽器在運(yùn)行PHP程序時(shí)總會(huì)卡死,造成約5~10分鐘的無響應(yīng)狀態(tài)收毫。我判斷一次讀取和處理的數(shù)據(jù)不能大于5000條攻走,所以我嵌套了另一個(gè)外部循環(huán),保證每次循環(huán)處理5000個(gè)數(shù)據(jù)此再,5000條數(shù)據(jù)都處理完陋气,再讀入下5000條。之后根據(jù)運(yùn)行結(jié)果來看引润,我已經(jīng)能夠做到秒級(jí)輸出處理結(jié)果了巩趁。
繪圖插件
我一開始打算使用PHP的類庫(kù):jpgraph來繪制統(tǒng)計(jì)圖表。但后來我被百度前端推出的圖標(biāo)插件echarts的效果吸引了淳附,因而決定使用echarts配合jQuery出圖议慰。
依舊是效率
我發(fā)現(xiàn)每次登錄系統(tǒng)都采取PHP運(yùn)算,讀入DBF后出圖是一個(gè)愚蠢的決定奴曙,因?yàn)檫@將導(dǎo)致打開數(shù)據(jù)庫(kù)别凹,可能處理大量不需要用戶看到的信息,從而拖慢機(jī)器速度洽糟。
我冥思苦想炉菲,最終發(fā)現(xiàn)了echarts插件支持通過json繪圖。我一下拍案而起坤溃,可以通過PHP處理數(shù)據(jù)庫(kù)一次拍霜,將獲得的、需要使用的數(shù)據(jù)儲(chǔ)存到j(luò)son中薪介。每次得到用戶的請(qǐng)求祠饺,都從json中加載數(shù)據(jù)。
這就避免了大量不需要的數(shù)據(jù)儲(chǔ)存在服務(wù)器上汁政,浪費(fèi)空間道偷,從而也避免了可能的安全問題缀旁。同時(shí),使用json相比于從DBF直接讀入數(shù)據(jù)快了很多倍勺鸦,一個(gè)json文件只有100kb而已(之前的dbf文件有足足300M)并巍。
之后我依舊使用上面每次讀取5000條數(shù)據(jù)的循環(huán),將讀取的數(shù)據(jù)以json格式輸出并儲(chǔ)存换途。
//for循環(huán)體
$row = dbase_get_record_with_names($db, $i);
switch ($row['JYQXDM']) {
//處理語句省略懊渡,處理結(jié)果是數(shù)組形式,賦給變量$res
}
json_encode($res);
echo $res;
在程序確認(rèn)無誤后怀跛,發(fā)現(xiàn)輸出無效距贷。頁面沒有顯示任何內(nèi)容。
中文編碼
json_encode函數(shù)要求json數(shù)據(jù)必須是utf-8編碼吻谋。但即使用UTF8編碼的字符忠蝗,使用json_encode也沒有輸出。后來我又查了一個(gè)小時(shí)漓拾,才找到了解決辦法阁最。
我在使用json_encode之前把字符用函數(shù)urlencode()處理一下,然后再json_encode骇两,輸出結(jié)果的時(shí)候在用函數(shù)urldecode()轉(zhuǎn)回來速种。測(cè)試代碼具體如下:
$testJSON=array('name'=>'中文字符串','value'=>'test');
foreach ( $testJSON as $key => $value ) {
$testJSON[$key] = urlencode ( $value );
}
echo urldecode ( json_encode ( $testJSON ) );
至此,PHP終于輸出了中文json格式低千。
關(guān)注我的諸位配阵,感謝你們的支持。
由于工作原因示血,最近沒有時(shí)間更新游戲開發(fā)教程和其他文章棋傍。我正著手于一個(gè)數(shù)據(jù)可視化系統(tǒng)的項(xiàng)目,可能在最近5天內(nèi)沒有時(shí)間再看簡(jiǎn)書并且回復(fù)大家的私信和評(píng)論难审。您可以繼續(xù)留言給我瘫拣,我會(huì)盡早回來繼續(xù)更新。