在C语言中获取文件大小的正确方法
在C语言中获取文件大小的正确方法
我正在进行一个套接字编程的作业,其中我需要在sparc和linux机器之间发送一个文件。在将文件以字符流的形式发送之前,我需要获取文件大小并告知客户端。以下是我尝试获取大小的一些方法,但我不确定哪个是正确的方法。\n为了测试目的,我创建了一个内容为“test”的文件(空格+字符串“test”)。\n方法1-使用fseeko()和ftello()\n这是我在https://www.securecoding.cert.org/confluence/display/c/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file上找到的一个方法。\n虽然fssek()存在一个问题,即“将文件位置指示器设置为文件末尾,例如fseek(file,0,SEEK_END),对于二进制流具有未定义的行为”,但据说fseeko()已经解决了这个问题,但它仅适用于POSIX系统(这没问题,因为我使用的环境是sparc和linux)。\n
fd = open(file_path, O_RDONLY); fp = fopen(file_path, "rb"); /* 确保文件是普通文件 */ if ((fstat(fd, &st) != 0) || (!S_ISREG(st.st_mode))) { /* 处理错误 */ } if (fseeko(fp, 0, SEEK_END) != 0) { /* 处理错误 */ } file_size = ftello(fp); fseeko(fp, 0, SEEK_SET); printf("文件大小 %zu\n", file_size);
\n这种方法可以很好地工作并正确获取大小。但是,它仅限于普通文件。我尝试在谷歌上搜索“普通文件”这个词,但我仍然不太了解它。我也不知道这个函数是否可靠适用于我的项目。\n方法2-使用strlen()\n由于我项目中文件的最大大小为4MB,所以我可以calloc一个4MB的缓冲区。然后,将文件读入缓冲区,并尝试使用strlen获取文件大小(或更准确地说是内容的长度)。由于strlen()是可移植的,我可以使用这种方法吗?代码片段如下:\n
fp = fopen(file_path, "rb"); fread(file_buffer, 1024*1024*4, 1, fp); printf("strlen %zu\n", strlen(file_buffer));
\n这种方法也可以工作,并返回\n
strlen 8
\n然而,我在互联网上找不到类似的使用这种方法的方法。所以我在思考是否我漏掉了什么,或者这种方法有一些我没有意识到的限制。
C语言中获取文件大小的正确方法
在C语言中,获取文件大小有时会变得比较困难。下面是一个关于如何正确获取文件大小的问题。
问题的出现原因:
问题的提问者认为可以通过简单地认为文件的最大大小是4MB来解决获取文件大小的问题。但是,这种方法并不可靠,因为strlen()函数在遇到第一个空字符时就会停止计数,因此可能会报告一个过小的值。另外,我们并不知道读取的数据是否包含空字符,因此它可能不是一个字符串。如果代码需要将数据作为字符串使用,应该将一个空字符追加在数据后面,并且分配的内存空间需要再增加1个字节。不过,在这种情况下,我希望文件以文本模式打开。
解决方法:
实际上,将整个文件读入内存可能并不是一个好主意。但是,如果确实需要将文件读入内存,可以按照以下方法来获取文件大小:
fp = fopen(file_path, "rb");
if (fp) {
#define MAX_FILE_SIZE 4194304
char *buf = malloc(MAX_FILE_SIZE);
if (buf) {
size_t numread = fread(buf, sizeof *buf, MAX_FILE_SIZE, fp);
// 如果需要,可以缩小内存空间
char *tmp = realloc(buf, numread);
if (tmp) {
buf = tmp;
// 使用包含numread个字符的buf
}
free(buf);
}
fclose(fp);
}
需要注意的是,许多操作系统在写入之前并不会使用分配的内存空间。
在C语言中,获取文件大小并不是一件容易的事情。为了得到正确的文件大小,我们应该避免使用strlen()函数,并使用fread()函数的返回值来获取文件大小。另外,我们还应该注意文件中是否包含空字符,并在需要将数据作为字符串使用时进行相应的处理。最后,读取整个文件到内存可能不是一个明智的选择,我们应该谨慎考虑是否需要这么做。
在C语言中获取文件大小的正确方法及解决方案
当我们需要获取一个普通文件的大小时,我们可以采用以下两种方法来实现。
第一种方法是通过打开文件来获取文件大小。具体步骤如下:
FILE* fp = fopen(...); if(fp) { fseek(fp, 0 , SEEK_END); long fileSize = ftell(fp); fseek(fp, 0 , SEEK_SET);// needed for next read from beginning of file ... fclose(fp); }
在这种方法中,我们首先打开文件,然后使用`fseek`函数将文件指针移动到文件的末尾,再使用`ftell`函数获取文件指针的位置,即文件大小。接着,我们再次使用`fseek`函数将文件指针移动到文件的开头,以便后续读取文件的操作。最后,我们使用`fclose`函数关闭文件。
第二种方法是通过不打开文件来获取文件大小。具体步骤如下:
#include#include #include struct stat buffer; int status; status = stat("path to file", &buffer); if(status == 0) { // size of file is in member buffer.st_size; }
在这种方法中,我们使用了`stat`函数来获取文件的信息,其中包括文件的大小。我们只需要将文件的路径传递给`stat`函数,并将结果保存在一个`struct stat`类型的变量中,然后可以通过`buffer.st_size`成员来获取文件的大小。
需要注意的是:
1) `ftell(fp)`函数返回的类型是`long`,而不是`size_t`。
2) 如果`fopen`函数是以文本模式打开的文件,则“...两个返回值之间的差异不一定是写入或读取的字符数的有意义的度量。”(引用自C11 §7.21.9.4 2)
3) 文件的大小可能超过`LONG_MAX`。