引言
有一天看見看到返回文件長度代碼返回值都是long,就感覺怪怪的, 一般32位long最大也就2G.
而大文件太多了, 一個Dota2安裝包估計都得10多G吧. 一般C得到文件長度代碼
/*
* 得到文件長度, 一種通用老的寫法
* path : 文件路徑
* : 返回文件長度
*/
long
file_getsize(const char * path) {
FILE * txt;
long rt;
if ((!path) || !(txt = fopen(path, "rb")))
return 0;
fseek(txt, 0, SEEK_END);
rt = ftell(txt);
fclose(txt);
return rt;
}
如上套路, 比較耿直的. 寫個測試代碼
#include <stdio.h>
/*
* 得到文件長度, 一種通用老的寫法
* path : 文件路徑
* : 返回文件長度
*/
long file_getsize(const char * path);
int main(int argc, char * argv[]) {
const char * path;
int i = 1;
while (i < argc) {
path = argv[i];
printf("%s => %ld\n", path, file_getsize(path));
++i;
}
return 0;
}
執行正常的測試結果看下圖

扯一點, 對於 fopen "rb"後面b表示采用二進制流方式處理, 默認是t文本模式. 前者速度快一點, 後者做了一些特殊處理.
主要是不同系統對換行符處理不同業務誕生的. 推薦用 b 二進制處理方式更快些.(21世紀是個裝b的年代, 全是BBB)
前言
這裡我們再做一個實驗 , 看下面大文件 . 繼續用上面代碼測試一下. 先看測試文件

測試結果如下

這時候我們需要用新的文件操作代碼,想辦法了. 其實上面ftell方式得到代碼, 來回移動文件指針性能很低.
因為文件大小操作系統知道, 直接問它要是最快的. 先在window 上寫一段代碼
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <inttypes.h>
/*
* 得到文件長度, windows 品台用法
* path : 文件路徑
* : 返回文件長度
*/
int64_t file_getsize(const char * path);
int main(int argc, char * argv[]) {
const char * path;
int i = 1;
while (i < argc) {
path = argv[i];
printf("%s => %ld\n", path, file_getsize(path));
++i;
}
return 0;
}
/*
* 得到文件長度, windows 上適用方法
* path : 文件路徑
* : 返回文件長度
*/
int64_t
file_getsize(const char * path) {
struct _stat64 info = { 0 };
if (!path || !*path)
return 0;
_stat64(path, &info);
return info.st_size;
}
上面就是完整的測試代碼, 主要通過 sys/stat.h 下面_stat64 函數得到 8字節長度的文件大小表示.
我們也繼續測試一下. 結果很滿意

到這裡我們. 在window上測試完畢.
正文
我們在linux上測試一下. 先看代碼我寫好的代碼 main_linux.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <inttypes.h>
/*
* 得到文件長度, linuxs 平台用法
* path : 文件路徑
* : 返回文件長度
*/
int64_t file_getsize(const char * path);
int main(int argc, char * argv[]) {
const char * path;
int i = 1;
// 測試demo
struct stat info;
printf("info.st_size size = %ld\n", sizeof(info.st_size));
printf("unsigned long size = %ld\n", sizeof(unsigned long));
while (i < argc) {
path = argv[i];
printf("%s => %ld\n", path, file_getsize(path));
++i;
}
return 0;
}
/*
* 得到文件長度, linux 上適用方法
* path : 文件路徑
* : 返回文件長度
*/
int64_t
file_getsize(const char * path) {
struct stat info = { 0 };
if (!path || !*path)
return 0;
stat(path, &info);
return info.st_size;
}
編譯命令
gcc -Wall -ggdb2 -o main_linux.out main_linux.c
後面查看 sys/stat.c 源碼
有興趣可以看看, 得到的結論是, linux會根據平台自動幫我們確定是 stat64 還是 stat. 我用的是64位的, 默認stat也是stat64.
返回的long 是 8字節. 可以看下面結果

這裡也解決了一個問題, 一般 off_t 結構是8字節的unsigned long 結構. window是long long結構. 不同平台實現不一樣.
如果希望這個函數是跨平台的 那麼 需要在 window 上做
#if defined(_MSC_VER)
# define stat _stat64
#endif
是不是很簡單. 就能夠讓我們的得到文件長度代碼跨平台了. 哎, 這種語言, 細節太多, 不利於生產. 大師們也老了, 改進的機會也少了, 太穩定了.
如果只為了快速的性能那麼沒有誰比C更適合的了, 更快速輕巧的了. 一切都是抉擇, 沒有最好, 只有最合適.
後記
錯誤是難免的, 歡迎交流提高. 也許我們年少的時候幻想著成為大英雄, 最終也只是拿著血汗錢成了房奴.

有夢想的人是令人羨慕的, 有夢想的人是令人惋惜的. 愛我所愛, 開心就好 ~~~~~~~~~