讀取文字檔的速度 LoadFromFile() |
|
dllee
站務副站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:321 回覆:2519 積分:1711 註冊:2002-04-15 發送簡訊給我 |
不知道各位有沒有將 TListBox 直接拿來顯示文字檔呢?
以下的程式片斷即是將 OpenDialog1 所選到的檔案要 ListBox1 顯示出來。
而小弟的問題在於 LoadFromFile( ) 的速度。
以一個 500KB 左右的文字檔,以小弟的 C900/256MB RAM/Win2000SP2 要花 2 秒多的時間,但一個 4MB 左右的文字檔卻是要花上 110 秒左右!! 實在是不成比例!如果您將本範例下載回去試試單步執行,可以發現就是那個 LoadFromFile() 在花時間... 請問要如何才能加快 LoadFromFile() 讀取文字檔的速度呢?或是用其他的方法也行,只要能夠顯示到 TListBox 上即可。或是 TMemo 上也行,只要時間能夠快一點,至少成比例,如 500KB 要 2 秒,那 4MB 16 秒... 而不是誇張的 110 秒。
void __fastcall TForm1::Button1Click(TObject *Sender) { if(OpenDialog1->Execute()) { TDateTime dtStart=Now(); ListBox1->Items->LoadFromFile(OpenDialog1->FileName); TDateTime dtEnd=Now(); TMemoryStream *Stream=new TMemoryStream; Stream->LoadFromFile(OpenDialog1->FileName); dtStart=dtEnd-dtStart; double dSec=double(dtStart)*24*60*60; // to 秒 AnsiString as; as=as.sprintf("File Size=%d\nLines=%d\nTotal Time= %.3f", Stream->Size,ListBox1->Items->Count,dSec); ShowMessage(as); Clipboard()->AsText=as; // 複製到剪貼簿 delete Stream; } }發表人 - dllee 於 2002/08/01 16:07:16
------
http://www.ViewMove.com |
dllee
站務副站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:321 回覆:2519 積分:1711 註冊:2002-04-15 發送簡訊給我 |
以下是實測的結果: File Size=45088
Lines=671
Total Time= 0.160 File Size=532661
Lines=8283
Total Time= 1.542 File Size=1206120
Lines=17928
Total Time= 9.483 File Size=1494504
Lines=21441
Total Time= 14.401 File Size=4191774
Lines=59952
Total Time= 113.653
------
http://www.ViewMove.com |
ccchen
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:61 回覆:940 積分:1394 註冊:2002-04-15 發送簡訊給我 |
測試檔案4.6M, 時間104秒. 若Create一個TStringList來load同樣檔案, 只須0.2秒(很可怕的差距), 看了一下Source Code, ListBOx之items雖宣告為TStrings, 實際上是TListBoxStrins, 讀寫均含許多Event. 用TMemo為3秒,好的多, 應可接受. 我用的是Delphi6, 印象中, Delphi3時之Tmemo行數有限制(count 為byte而已), Delphi6已無問題, 你可能須測試你的版本是否會被刪除.
|
dllee
站務副站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:321 回覆:2519 積分:1711 註冊:2002-04-15 發送簡訊給我 |
引言: 測試檔案4.6M, 時間104秒. 若Create一個TStringList來load同樣檔案, 只須0.2秒(很可怕的差距), 看了一下Source Code, ListBOx之items雖宣告為TStrings, 實際上是TListBoxStrins, 讀寫均含許多Event. 用TMemo為3秒,好的多, 應可接受. 我用的是Delphi6, 印象中, Delphi3時之Tmemo行數有限制(count 為byte而已), Delphi6已無問題, 你可能須測試你的版本是否會被刪除.一開始我是使用 TStringList::LoadFromFile() 來讀檔的,可是速度一樣是慢,而我發現最慢的地方是 TStrings::Add() 很慢,因為我已經把 TStringList 及 TStrings 的底層轉成 C 自己作,結果就是慢在 Add()! 我的 BCB 是 5 Enp 也許 Delphi6 在 TStringList 已有改進,不知您是否方便將 TStringList 的那個 VCL source 寄給我呢? 如果可以請寄到 dllee@edirect168.com 我會將不同處作測試,再將結果報告出來。 P.S. 我現在已改用 TMemo ,我發現 TMemo 的底層是 Windows 內建的 Edit 元件,使用 SendMessage() 的方式向系統存取該 Edit 元件,而速度是比 TListBox 要快得多。
------
http://www.ViewMove.com |
ccchen
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:61 回覆:940 積分:1394 註冊:2002-04-15 發送簡訊給我 |
|
dllee
站務副站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:321 回覆:2519 積分:1711 註冊:2002-04-15 發送簡訊給我 |
程式更新了(8/1)!
switch(RadioGroup1->ItemIndex) { case 0: // TListBox { ListBox1->Items->LoadFromFile(OpenDialog1->FileName); } break; case 1: // TMemo { Memo1->Lines->LoadFromFile(OpenDialog1->FileName); } break; case 2: // TStringList { sList=new TStringList; sList->LoadFromFile(OpenDialog1->FileName); delete sList; } break; }而在比對了 BCB5 及 D6 的 TStrings/TStringList 後,發現,沒有什麼大不同,而使用後 TMemo::LoadFromFile() File Size=15918385 Lines=236513 Total Time= 6.980 TStringList::LoadFromFile() File Size=15918385 Lines=0 Total Time= 1.111 而 TListBox 約是 25 分鐘!!我已放棄使用 TListBox 了。 原本會使用 TListBox 的原因,只因為想要有點選到的那一行能「反白」或是有標示的效果。 switch(RadioGroup1->ItemIndex) { case 0: // TListBox { if(iLine > ListBox1->Items->Count) iLine=ListBox1->Items->Count; // TListBox 只要指定 ItemIndex 即可「標示」所選的那一行 ListBox1->ItemIndex=iLine-1; } break; case 1: // TMemo { if(iLine > Memo1->Lines->Count) iLine=Memo1->Lines->Count; // TMemo 必需使用 Select 才能有「標示」的效果 Memo1->SelStart=SendMessage(Memo1->Handle, EM_LINEINDEX, iLine-1, 0); Memo1->SelLength=Memo1->Lines->Strings[iLine-1].Length(); } break; case 2: // TStringList { // NO GUI } break;改用 TMemo ,在字串轉換速度已可接受,但是由以上的程式碼,我只能作到選擇「有字的部分」如果有一行是沒有字的,那就沒有任何反白。 請問要如何在 TMemo 中作出類似 TListBox 那樣反白一行的效果呢?
------
http://www.ViewMove.com |
ccchen
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:61 回覆:940 積分:1394 註冊:2002-04-15 發送簡訊給我 |
引言: 改用 TMemo ,在字串轉換速度已可接受,但是由以上的程式碼,我只能作到選擇「有字的部分」如果有一行是沒有字的,那就沒有任何反白。 請問要如何在 TMemo 中作出類似 TListBox 那樣反白一行的效果呢?我想那很難,也有很多衍生問題 1. 仔細看了一下memo.lines之限制, 在wind9x只有64k, 2000則無問題 2. 原就只是一個TCustomEdit,元件上並無row之概念只靠#13#10在處理,若要做到幾乎已是寫一個listbox,即使做到可能也會破壞原SelText之架構 一個另類的想法, 須要BDE不知你是否接受 用BDE Table, 由於Table有Cache buffer, User會感覺很快而DBGrid之options,可將dgTitles, dgRowLines,dgIndicator設為False, 看起來和listbox沒兩樣且預留下之功能更多. with Table1 do begin DatabaseName:='d:\'; //filepath TableType:= ttASCII; TableName:='SINI_HRS'; //filename, 延伸檔名若不為.txt, 須加ext OPEN; end;當然須加DataSource連上DBGrid 快的讓你滿意, 缺點是含了BDE 我用Delphi6 TStringlist--RunTime Create之TStringlist, 而不是cast Listbox.items, 0.22秒為何BCB會如此慢? 發表人 - ccchen 於 2002/08/01 18:33:52 |
dllee
站務副站長 ![]() ![]() ![]() ![]() ![]() ![]() 發表:321 回覆:2519 積分:1711 註冊:2002-04-15 發送簡訊給我 |
引言: 我用Delphi6 TStringlist--RunTime Create之TStringlist, 而不是cast Listbox.items, 0.22秒為何BCB會如此慢?單純用 TStringList 是很快呀 TStringList::LoadFromFile() File Size= 15918385 Bytes Total Time= 1.111 秒 用 BDE 可以加快,可是我不想使用 BDE,因為我要寫的程式只是簡單地處理我自己程式在執行過程中所產生的 LOG,讓我方便 Offline Debug 我的程式,這樣的小程式不希望說包著 BDE,否則到沒有裝 BDE 的電腦就不能用了... 在這過程中,硬 K 了不少 Delphi 的原始碼,感覺還有點吃力。 謝謝您的幫忙。
------
http://www.ViewMove.com |
renard
一般會員 ![]() ![]() 發表:3 回覆:43 積分:24 註冊:2007-06-29 發送簡訊給我 |
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |