以C

时间:2016-02-14 10:53:11

标签: c linux sockets filesize

我正在进行socket编程中的一项任务,我必须在sparc和linux机器之间发送一个文件。在char流中发送文件之前,我必须获取文件大小并告诉客户端。以下是我试图获得尺寸的一些方法,但我不确定哪一种是正确的。

出于测试目的,我创建了一个内容为“test”(空格+(字符串)测试)

的文件

方法1 - 使用fseeko()和ftello()

这是我在https://www.securecoding.cert.org/confluence/display/c/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file找到的方法 虽然fssek()的问题是“将文件位置指示器设置为文件结尾,与fseek(文件,0,SEEK_END)一样,但是对于二进制流具有未定义的行为”,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);

此方法正常工作并正确获取大小。但是,它仅限于常规文件。我试图谷歌术语“常规文件”但我仍然不太了解它。我不知道这个功能对我的项目是否可靠。

方法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

但是,我在使用此方法的Internet上看不到任何类似的方法。所以我想也许我错过了一些东西,或者这种方法存在一些局限性,我还没有意识到。

2 个答案:

答案 0 :(得分:7)

常规文件意味着它没有什么特别的东西,如设备,插座,管道等,但是"正常"文件。 似乎在发送之前通过您的任务描述必须检索普通文件的大小。 所以你的方式是正确的:

user_id

但你可以在不打开文件的情况下完成:

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);
}

答案 1 :(得分:0)

OP可以 easy 的方式做到" max。我项目中文件的大小是4MB"。

使用strlen()的返回值,而不是使用fread()stlen()在第一个空字符处停止,因此可能报告的值太小。 @Sami Kuhmonen此外,我们不知道读取的数据包含任何空字符,因此它可能不是字符串。如果代码需要将数据用作字符串,则附加空字符(并分配+1)。但在这种情况下,我希望文件需要在文本模式下打开。

请注意,许多操作系统在写入之前甚至不使用已分配的内存 Why is malloc not "using up" the memory on my computer?

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);
}

注意:将整个文件读入内存可能不是最好的选择。