原理:將文件指針移至末尾,ftell 返回距文件開頭的字節偏移量,即文件大小。
#include <stdio.h>
#include <stdlib.h>
long get_filesize_fseek(const char *path) {
FILE *fp = fopen(path, "rb"); // 二進制模式避免換行符轉換影響
if (!fp) return -1;
if (fseek(fp, 0, SEEK_END) != 0) { fclose(fp); return -1; }
long size = ftell(fp);
fclose(fp);
return size;
}
int main(void) {
long sz = get_filesize_fseek("Q.txt");
if (sz >= 0) printf("文件大小: %ld 字節\\n", sz);
else perror("獲取失敗");
return 0;
}
\r\n 轉為 \n,導致 ftell 值小於磁盤實際大小。fseeko/ftello (POSIX) 或 _fseeki64 (Windows)。一次調用獲取大小、時間、權限、設備號等完整屬性。
#include <stdio.h>
#include <sys/stat.h>
#include <time.h>
// Linux/macOS
long get_filesize_stat(const char *path) {
struct stat st;
if (stat(path, &st) != 0) return -1;
return st.st_size;
}
// Windows (MSVC/MinGW)
long get_filesize_stat_win(const char *path) {
struct _stat st;
if (_stat(path, &st) != 0) return -1;
return st.st_size;
}
int main(void) {
struct _stat buf;
if (_stat("Q.txt", &buf) == 0) {
printf("大小: %ld\\n", buf.st_size);
printf("磁盤: %c:\\n", buf.st_dev + 'A');
printf("創建時間: %s", ctime(&buf.st_ctime));
printf("修改時間: %s", ctime(&buf.st_mtime));
printf("訪問時間: %s", ctime(&buf.st_atime));
} else perror("stat失敗");
return 0;
}
| 字段 | 含義 |
|---|---|
st_size | 文件大小(字節) |
st_dev | 所在設備號 |
st_ino | inode 號 |
st_mode | 權限與類型 |
st_uid/st_gid | 所有者用戶/組 ID |
st_atime | 最後訪問時間 |
st_mtime | 最後修改時間 |
st_ctime | 狀態改變時間(Windows 為創建時間) |
| 場景 | 推薦 | 理由 |
|---|---|---|
| 僅需大小、跨平台 | fseek/ftell | 純標準 C,無平台依賴 |
| 需時間/權限/設備等元數據 | stat | 一次調用全拿,避免多次系統調用 |
| 大文件 > 2GB (32位) | fseeko/ftello 或 _fseeki64 | 64 位偏移量 |
| 高性能、避免打開文件 | stat | 無需 fopen,僅元數據查詢 |
fopen(path, "r") 導致 ftell 不準 —— 永遠用 "rb"。ftell 返回 -1L 表示出錯,需檢查 errno。_stat 與 POSIX stat 結構體字段基本對應,但時間語義略異(st_ctime)。stat 也成功,但 st_size 語義不同(通常為塊大小),勿作為文件大小判斷依據。