从C中的二进制文件中读取

时间:2015-03-21 19:29:22

标签: c sockets printf binaryfiles fgets

我目前正在开发一个项目,我必须从二进制文件中读取并通过套接字发送它,并且我很难尝试发送整个文件。

这是我到目前为止所写的内容:

        FILE *f = fopen(line,"rt");
        //size = lseek(f, 0, SEEK_END)+1;
        fseek(f, 0L, SEEK_END);
        int size = ftell(f);
        unsigned char buffer[MSGSIZE];
        FILE *file = fopen(line,"rb");
        while(fgets(buffer,MSGSIZE,file)){
            sprintf(r.payload,"%s",buffer);
            r.len = strlen(r.payload)+1;
            res = send_message(&r);
            if (res < 0) {
                perror("[RECEIVER] Send ACK error. Exiting.\n");
                return -1;
            }   
        }

我认为它与我读到的缓冲区大小有关,但我不知道它的正确公式是什么。

还有一件事,sprintf是否正确完成了?

3 个答案:

答案 0 :(得分:3)

如果您正在阅读二进制文件,NUL字符可能会出现在文件的任何位置。

因此,使用像sprintfstrlen这样的字符串函数是一个坏主意。 如果您确实需要使用第二个缓冲区(buffer),则可以使用memcpy。 您也可以直接读入r.payload(如果r.payload已经分配了足够的大小)。

您正在寻找fread二进制文件。 fread的返回值告诉您在缓冲区中读取了多少字节。

您也可以考虑再次致电fseek。 见How can I get a file's size in C?

也许你的代码看起来像这样:

#include <stdint.h>
#include <stdio.h>

#define MSGSIZE 512

struct r_t {
  uint8_t payload[MSGSIZE];
  int len;
};

int send_message(struct r_t *t);

int main() {
  struct r_t r;
  FILE *f = fopen("test.bin","rb");
  fseek(f, 0L, SEEK_END);
  size_t size = ftell(f);
  fseek(f, 0L, SEEK_SET);
  do {
    r.len = fread(r.payload, 1, sizeof(r.payload), f);
    if (r.len > 0) {
      int res = send_message(&r);
      if (res < 0) {
        perror("[RECEIVER] Send ACK error. Exiting.\n");
        fclose(f);
        return -1;
      }
    }   
  } while (r.len > 0);
  fclose(f);
  return 0;
}

答案 1 :(得分:0)

不,sprintf未正确完成。它容易出现缓冲区溢出,这是一个非常严重的安全问题。

我会考虑将文件作为例如1024字节的块而不是逐行的,所以我会用fread调用替换fgets调用。

为什么要打开文件两次?显然要获得它的大小,但你只能打开它一次并跳回文件的开头。并且,您没有使用您阅读的尺寸。

答案 2 :(得分:0)

是二进制文件还是文本文件? fgets()假设您正在读取文本文件 - 它在换行符处停止 - 但您说它是一个二进制文件并用&#34; rb&#34;打开它。 (实际上,第一次使用&#34; rt&#34;打开它时,我认为这是一个错字)。

IMO你永远不应该使用sprintf。写入缓冲区的字符数取决于传入的参数,在这种情况下,如果没有&#39; \ 0&#39;在缓冲区中,你无法预测将多少字节复制到r.payload,并且很有可能会溢出该缓冲区。

我认为sprintf()将是第一个要解决的问题。使用memcpy(),您可以准确地告诉它要复制多少字节。