Re: [問題] 如何知道一個檔案有幾行

看板C_and_CPP作者 (藍影)時間13年前 (2011/06/10 17:24), 編輯推噓0(0011)
留言11則, 4人參與, 最新討論串2/4 (看更多)
※ 引述《CS1DADA (CS1DADA)》之銘言: : 小弟目前想到的是使用fgetchar() : 計算一個file中有多少個'\n', : 根據'\n'的個數有多少來算行數 : 不知道有沒有更快或是不同的想法呢? : 謝謝 既然推文中也有人開始注意, 由於小弟之前處理檔案都不算小,對於讀取速度上小有研究, 放上一些過程和數據,目前想到比 fgets 快、穩的方法在 step 4 皆為 C 可使用之函式庫,說明有些冗長,請多包涵;有誤請不吝指正。 -------- step1 : 產生測試資料 (1) 固定產生一 LINE_CNT 行之檔案 (2) 第 i 行之字元數,限定為 100~2000 字元,以 rand 決定 (3) 每個字元產生方式: rand() % 26 + 'a' 程式碼大概長這樣 int i, j, k; FILE *fp=fopen(FILENAME, "w"); srand(0); // 不同電腦、相同compiler產生結果一樣 for(i=0; i!=LINE_CNT; ++i){ // 產生 LINE_CNT 行 j = rand() % 1901 + 100; // 第 i 行產生 j 個 a~z, j: [100, 2000] for(k=0; k!=j; ++k) fputc(rand()%26 + 'a', fp); fputc('\n', fp); } fclose(fp); ※ 實際設 LINE_CNT = 200 萬, 產生大小約 1.93 GB -------- step2 : 以 fgetc 進行 char ch; int line_cnt=0; FILE *fp=fopen(FILENAME, "r"); t1=clock(); while( ( ch = fgetc(fp)) != EOF) if(ch=='\n') ++line_cnt; t2=clock(); fclose(fp); ※ 這是最慢的方式,非常不建議這麼做 --------- step 3: 以 fgets 進行 int line_cnt=0; char buf[BUF_SIZE+1]={0}; FILE *fp=fopen(FILENAME, "r"); t1=clock(); while(fgets(buf, BUF_SIZE, fp)!=NULL) ++line_cnt; t2=clock(); fclose(fp); ※ 事實上這段碼有「極小」可能會出包,該檔案若有幾行特別特別長的話, ※ 便不能確信 fgets 能一次抓完一行, 最保險是抓完後再去判斷 buf[len-1]='\n' ※ 但用到 brach 感覺就不好了 ---------- step 4: 用 fread 進行 t1=clock(); while(BUF_SIZE==fread(buf, 1, BUF_SIZE, fp)){ ptr = (char*)strchr(buf, '\n'); while(ptr!=NULL){ ++line_cnt; ptr = (char*)strchr(ptr+1, '\n'); } } t2=clock(); ※ 用 fread 比 fgets 好的地方在於,每次必抓 BUF_SIZE 這麼多字, ※ 若每行只有十幾二十個字,用 fgets 還是要分很多次抓取 ----------- Result : VS2008, 開 O2, fgetc:143.953 secs fgets:106.406 secs * fread: 47.718 secs 檔案讀取之速度原則大致上應有二點要注意: (a) 能減少讀檔次數就盡量減少, 將動作放到 memory 裡進行 (b) 注意有些函式做 parse 速度非常慢 ------------ 以上, 供參考. -- YouLoveMe() ? LetItBe() : LetMeFree(); -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 180.177.73.222

06/10 19:29, , 1F
假如你有unistd.h 就可以用read() XD
06/10 19:29, 1F

06/10 19:40, , 2F
用 fopen 得到的 FILE* 原本就配有 buffer 大小是 BUF_SIZ
06/10 19:40, 2F

06/10 19:41, , 3F
直接把那個 buffer 配大一點就能加速了 也不用自己管
06/10 19:41, 3F

06/10 19:43, , 4F
有格式化需求才考慮自己管 不然會多花一次 memcpy
06/10 19:43, 4F

06/10 20:12, , 5F
試問adxis,照您的說法,該如何撰之?懇請賜教.
06/10 20:12, 5F

06/10 20:13, , 6F
@firejox,確實低階之write/read應會再快些.
06/10 20:13, 6F

06/10 21:47, , 7F
以c來講的話,第四個方法最好.畢竟unistd.h無法跨平台
06/10 21:47, 7F

06/10 21:48, , 8F
而且講實話,當初我是用弟三個去算的,還真的沒想到4
06/10 21:48, 8F

06/11 05:04, , 9F
t桑寫法基本上只差系統buffer 那邊沒有利用到了
06/11 05:04, 9F

06/11 05:05, , 10F
之前回原原po文有回 只是沒有寫完整code
06/11 05:05, 10F

06/11 05:06, , 11F
至於memcpy 這邊是我講錯了 見諒
06/11 05:06, 11F
文章代碼(AID): #1DyUBD7Q (C_and_CPP)
討論串 (同標題文章)
文章代碼(AID): #1DyUBD7Q (C_and_CPP)