[C#] 如何從大量JSON檔案中找尋關鍵字(JSON.net 還原篇)
接下來要發一些有關於'搜尋' 資料的文章..
最近遇到一個需求,就是我必須要在一大堆資料 (檔案) 中找尋到某一個關鍵字
偏偏那不是純文字檔,而是 JSON 的格式…
這時候就挑起我的好奇心,到底怎樣可以快速找尋到我要的資料..
首先,要先解決我的問題如何找到資料…
介紹範例資料
首先我在 Source 這檔案夾下面建立 10 萬筆資料,不多,但是也不太少,但是產生跟複製的時候足以讓我電腦 hang 住..
這資料結構長這樣
{
"Id":"4",
"Memo":"的,你快挖了丁老賊的眼珠出來,給我報仇。」蕭峰一時難以明白其間真相,目光環掃,在人君中見到了段正淳和",
"Birthday":"1900-01-05T00:00:00",
"Age":4
}
上述為了顯示好看在資料中是無分行的 JSON 資料 命名從 1~100000 所以 Id 跟檔名相同,Age 也是,至於 Memo 資料
1~50000 是從金庸小說天龍八部隨機取出 50 字,50000~100000 是從金庸小說射鵰英雄傳裡面隨機取出 50 字,做成測試資料..
所以您可以透過 段譽、蕭峰等關鍵字搜尋 您可以搜尋出 1~50000 的資料,如果是搜尋 郭靖、黃蓉、洪七公 你會搜尋到 50001~100000 的資料
我在 1,1199,49999,99999 的 Memo 欄位中都加上了當麻的字樣,方便我進行測試…
ps. 下載範例時候,可以下載到這 100000 個檔案,解壓縮的時候可能會花一點時間。
進行搜尋
接下來我們就是把"他們" 讀取出來進行搜尋…
C# Code :
// 使用 Stopwatch 進行監看花費時間
Stopwatch sw = new Stopwatch();
// 監看開始
sw.Start();
var sourceDirectoryInfo = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory + "\\Source\\");
// 因為未知物件型態所以使用 dynamic
//File.ReadAllText(x.FullName) 取出檔案夾下面所有檔案 並且讀取內容
//JsonConvert.DeserializeObject<dynamic>(File.ReadAllText(x.FullName))) 將其 unboxing .
//JsonConvert.DeserializeObject<dynamic>(File.ReadAllText(x.FullName))).Where(x => x.Memo.ToString().Contains(txtKeyword.Text)) 搜尋出所帶有的關鍵字
dynamic allObjects =
sourceDirectoryInfo.GetFiles().Select(
x => JsonConvert.DeserializeObject<dynamic>(File.ReadAllText(x.FullName))).Where(x => x.Memo.ToString().Contains(txtKeyword.Text)).ToArray();
// 監看結束
sw.Stop();
Response.Write("花費時間:" + sw.Elapsed + " <br /><hr />");
Response.Write("資料筆數:" + allObjects.Length + "<br /><hr />");
Response.Write("Result:<br />");
foreach (dynamic obj in allObjects)
{
Response.Write("Id:" + obj.Id + " Memo=" + obj.Memo.ToString().Replace(txtKeyword.Text, "<span style='color:red'>" + txtKeyword.Text + "</span>") + "<br />");
}
看一下結果:
搜尋 關鍵字: 當麻
連續測試五次分別時間為:
第一次:花費時間:00:00:50.4927420
第二次:花費時間:00:00:26.2773594
第三次:花費時間:00:00:26.2117427
第四次:花費時間:00:00:27.0565036
第五次:花費時間:00:00:26.7758970
搜尋 關鍵字: 黃蓉
花費時間:00:00:27.6738803
搜尋 關鍵字: 段譽
花費時間:00:00:27.2426821
結論
目標資料十萬筆,讀取檔案後,使用 JSON.net 還原其物件,再用.net framework 內建的 Contains 去判斷是否有此關鍵字,
無論資料大小目前大約都在 26~27 秒可以完成,暫時算達到搜尋任務….
範例下載