我正在进行套接字编程的任务,我必须在sparc和linux机器之间发送一个文件。 在charstream中发送文件之前,我必须获取文件大小并告诉客户端。 这里有一些我试图得到的大小,但我不知道哪一个是适当的。
为了testing目的,我创build了一个内容为“test”(空格+(string)testing)的文件,
方法1 – 使用fseeko()和ftello()
这是我在https://www.securecoding.cert.org/confluence/display/c/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+ + + +常规+文件的+大小+虽然fssek()有一个问题“设置文件位置指示器到文件结束,与fseek(文件,0,SEEK_END)一样,具有未定义的二进制行为stream“,fseeko()据说解决了这个问题,但它只适用于POSIX系统(这很好,因为我使用的环境是sparc和linux)
fd = open(file_path, O_RDONLY); fp = fopen(file_path, "rb"); /* Ensure that the file is a regular file */ if ((fstat(fd, &st) != 0) || (!S_ISREG(st.st_mode))) { /* Handle error */ } if (fseeko(fp, 0 , SEEK_END) != 0) { /* Handle error */ } file_size = ftello(fp); fseeko(fp, 0, SEEK_SET); printf("file size %zu\n", file_size);
此方法工作正常,并获得正确的大小。 但是,它仅限于常规文件。 我试图谷歌的“常规文件”一词,但我还是不完全理解它。 我不知道这个function对我的项目是否可靠。
方法2 – 使用strlen()
由于最大。 我的项目中的文件大小是4MB,所以我可以调用一个4MB的缓冲区。 之后,该文件被读入缓冲区,我试图使用strlen来获取文件大小(或更正确的内容的长度)。 由于strlen()是可移植的,我可以使用这个方法吗? 代码片段是这样的
fp = fopen(file_path, "rb"); fread(file_buffer, 1024*1024*4, 1, fp); printf("strlen %zu\n", strlen(file_buffer));
这个方法也可以工作并返回
strlen 8
但是,我看不到使用这种方法在互联网上的任何类似的方法。 所以我想,也许我已经错过了一些东西,或者我没有意识到这个方法有一些局限性。
常规文件意味着它不是什么特殊的设备,套接字,管道等,但“正常”的文件。 看来在发送之前你的任务描述必须检索正常文件的大小。 所以你的方式是正确的:
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); }
但是你可以不用打开文件
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> struct stat buffer; int status; status = stat("path to file", &buffer); if(status == 0) { // size of file is in member buffer.st_size; }
OP可以做到这一点,因为“我的项目文件的最大大小是4MB”。
而不是使用strlen()
,使用fread()
的返回值。 stlen()
停在第一个空字符上,所以可能会报告太小的值。 另外我们也不知道读取的数据是否包含任何空字符,所以它可能不是一个字符串。 如果代码需要使用数据作为字符串,则追加一个空字符(并分配+1)。 但在这种情况下,我希望文件需要在文本模式下打开。
请注意,许多操作系统甚至在写入之前都不使用分配的内存。
为什么malloc不是“用尽”我的电脑上的内存?
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); // shrink if desired char *tmp = realloc(buf, numread); if (tmp) { buf = tmp; // Use buf with numread char } free(buf); } fclose(fp); }
注意:将整个文件读入内存可能不是最好的开始。