[英]How do you determine the size of a file in C?
如何計算文件的大小(以字節為單位)?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
基於 NilObject 的代碼:
#include <sys/stat.h>
#include <sys/types.h>
off_t fsize(const char *filename) {
struct stat st;
if (stat(filename, &st) == 0)
return st.st_size;
return -1;
}
變化:
const char
。struct stat
定義,該定義缺少變量名稱。-1
而不是0
,這對於空文件來說是不明確的。 off_t
是有符號類型,所以這是可能的。 如果你想讓fsize()
在出錯時打印一條消息,你可以使用這個:
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
off_t fsize(const char *filename) {
struct stat st;
if (stat(filename, &st) == 0)
return st.st_size;
fprintf(stderr, "Cannot determine size of %s: %s\n",
filename, strerror(errno));
return -1;
}
在 32 位系統上,您應該使用選項-D_FILE_OFFSET_BITS=64
編譯它,否則off_t
最多只能保存 2 GB 的值。 有關詳細信息,請參閱Linux中大文件支持的“使用 LFS”部分。
不要使用int
。 如今,大小超過 2 GB 的文件很常見
不要使用unsigned int
。 大小超過 4 GB 的文件很常見,因為一些不太常見的污垢
IIRC 標准庫將off_t
定義為一個無符號的 64 位整數,這是每個人都應該使用的。 幾年后,當我們開始有 16 艾字節的文件時,我們可以將其重新定義為 128 位。
如果你在 Windows 上,你應該使用GetFileSizeEx - 它實際上使用一個有符號的 64 位整數,所以他們會開始遇到 8 艾字節文件的問題。 愚蠢的微軟! :-)
Matt 的解決方案應該有效,只是它是 C++ 而不是 C,並且不需要初始告訴。
unsigned long fsize(char* file)
{
FILE * f = fopen(file, "r");
fseek(f, 0, SEEK_END);
unsigned long len = (unsigned long)ftell(f);
fclose(f);
return len;
}
也為你修好了支具。 ;)
更新:這並不是最好的解決方案。 它在 Windows 上僅限於 4GB 文件,並且可能比僅使用特定於平台的調用(如GetFileSizeEx
或stat64
。
**不要這樣做( 為什么? ):
引用我在網上找到的 C99 標准文檔:“將文件位置指示符設置為文件結尾,與
fseek(file, 0, SEEK_END)
,對於二進制流具有未定義的行為(因為可能出現尾隨空字符)或對於任何具有狀態相關編碼但不一定以初始移位狀態結束的流。**
把定義改成int,這樣可以傳輸錯誤信息,然后用fseek()
和ftell()
來確定文件大小。
int fsize(char* file) {
int size;
FILE* fh;
fh = fopen(file, "rb"); //binary mode
if(fh != NULL){
if( fseek(fh, 0, SEEK_END) ){
fclose(fh);
return -1;
}
size = ftell(fh);
fclose(fh);
return size;
}
return -1; //error
}
POSIX標准有自己的方法來獲取文件大小。
包含sys/stat.h
標頭以使用該函數。
stat(3)
獲取文件統計信息。st_size
屬性。注意:它將大小限制為4GB
。 如果不是Fat32
文件系統,則使用 64 位版本!
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char** argv)
{
struct stat info;
stat(argv[1], &info);
// 'st' is an acronym of 'stat'
printf("%s: size=%ld\n", argv[1], info.st_size);
}
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char** argv)
{
struct stat64 info;
stat64(argv[1], &info);
// 'st' is an acronym of 'stat'
printf("%s: size=%ld\n", argv[1], info.st_size);
}
ANSI C沒有直接提供確定文件長度的方法。
我們將不得不使用我們的頭腦。 現在,我們將使用搜索方法!
#include <stdio.h>
int main(int argc, char** argv)
{
FILE* fp = fopen(argv[1]);
int f_size;
fseek(fp, 0, SEEK_END);
f_size = ftell(fp);
rewind(fp); // to back to start again
printf("%s: size=%ld", (unsigned long)f_size);
}
如果文件是
stdin
或管道。 POSIX,ANSI C將不起作用。
如果文件是管道或stdin
,它將返回0
。意見:您應該改用POSIX標准。 因為,它支持 64 位。
如果您可以使用 std c 庫:
#include <sys/stat.h>
off_t fsize(char *file) {
struct stat filestat;
if (stat(file, &filestat) == 0) {
return filestat.st_size;
}
return 0;
}
如果您正在構建 Windows 應用程序,請使用GetFileSizeEx API,因為 CRT 文件 I/O 很混亂,尤其是在確定文件長度時,由於不同系統上文件表示的特殊性;)
我找到了一個使用 fseek 和 ftell 的方法,以及一個關於這個問題的線程,其中的答案是它不能以另一種方式在 C 中完成。
您可以使用像NSPR (支持 Firefox 的庫)這樣的可移植性庫。
我使用這組代碼來查找文件長度。
//opens a file with a file descriptor
FILE * i_file;
i_file = fopen(source, "r");
//gets a long from the file descriptor for fstat
long f_d = fileno(i_file);
struct stat buffer;
fstat(f_d, &buffer);
//stores file size
long file_length = buffer.st_size;
fclose(i_file);
在普通ISO C中,只有一種方法可以確定保證有效的文件大小:從頭讀取整個文件,直到遇到文件結尾。
然而,這是非常低效的。 如果您想要一個更有效的解決方案,那么您將不得不
stat
或 Microsoft GetFileSize
上的 GetFileSize。與其他答案所建議的相反,不能保證以下代碼有效:
fseek( fp, 0, SEEK_END );
long size = ftell( fp );
即使我們假設數據類型long
足夠大以表示文件大小(這在某些平台上是有問題的,尤其是 Microsoft Windows),發布的代碼也存在以下問題:
不保證發布的代碼適用於文本流,因為根據ISO C11 標准的 §7.21.9.4 ¶2, ftell
返回的文件 position 指標的值包含未指定的信息。 僅對於二進制流,此值保證是從文件開頭算起的字符數。 文本流沒有這樣的保證。
發布的代碼也不能保證在二進制流上工作,因為根據ISO C11 標准的 §7.21.9.2 ¶3 ,二進制流不需要有意義地支持SEEK_END
。
也就是說,在大多數常見平台上,如果我們假設數據類型long
足夠大以表示文件的大小,則發布的代碼將起作用。
但是,在 Microsoft Windows 上,字符\r\n
(回車后跟換行符)將被轉換為\n
對於文本流(但不是二進制流),因此您獲得的文件大小將計算\r\n
作為兩個字節,盡管您只是在文本模式下讀取單個字符( \n
)。 因此,您獲得的結果將不一致。
在基於POSIX的平台(例如 Linux)上,這不是問題,因為在那些平台上,文本模式和二進制模式之間沒有區別。
從 Windows 文件詳細信息中提取的C++ MFC ,不確定這是否比搜索性能更好,但如果它是從元數據中提取的,我認為它更快,因為它不需要讀取整個文件
ULONGLONG GetFileSizeAtt(const wchar_t *wFile)
{
WIN32_FILE_ATTRIBUTE_DATA fileInfo;
ULONGLONG FileSize = 0ULL;
//https://docs.microsoft.com/nl-nl/windows/win32/api/fileapi/nf-fileapi-getfileattributesexa?redirectedfrom=MSDN
//https://docs.microsoft.com/nl-nl/windows/win32/api/fileapi/ns-fileapi-win32_file_attribute_data?redirectedfrom=MSDN
if (GetFileAttributesEx(wFile, GetFileExInfoStandard, &fileInfo))
{
ULARGE_INTEGER ul;
ul.HighPart = fileInfo.nFileSizeHigh;
ul.LowPart = fileInfo.nFileSizeLow;
FileSize = ul.QuadPart;
}
return FileSize;
}
這是一個返回文件大小的簡單而干凈的函數。
long get_file_size(char *path)
{
FILE *fp;
long size = -1;
/* Open file for reading */
fp = fopen(path, "r");
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fclose(fp);
return
}
嘗試這個 -
fseek(fp, 0, SEEK_END);
unsigned long int file_size = ftell(fp);
rewind(fp);
這樣做是首先,尋找文件的末尾; 然后,報告文件指針在哪里。 最后(這是可選的)它倒回到文件的開頭。 注意fp
應該是一個二進制流。
file_size 包含文件包含的字節數。 請注意,由於(根據 climits.h) unsigned long 類型被限制為 4294967295 字節(4 GB),如果您可能處理大於該值的文件,則需要找到不同的變量類型。
我有一個僅適用於stdio.h
的函數。 我非常喜歡它,而且效果很好,而且非常簡潔:
size_t fsize(FILE *File) {
size_t FSZ;
fseek(File, 0, 2);
FSZ = ftell(File);
rewind(File);
return FSZ;
}
您可以打開文件,使用從文件底部相對的 0 偏移量
#define SEEKBOTTOM 2
fseek(handle, 0, SEEKBOTTOM)
fseek 返回的值是文件的大小。
我很長一段時間沒有用 C 編寫代碼,但我認為它應該可以工作。
如何計算文件大小(以字節為單位)?
#include <stdio.h>
unsigned int fsize(char* file){
//what goes here?
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.