[英]reading from a binary file in C
我目前在一个项目中,我必须从二进制文件中读取并通过套接字发送,而在尝试发送整个文件时遇到了困难。
到目前为止,这是我写的内容:
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是否正确完成?
如果您正在读取二进制文件,则NUL字符可能会出现在文件中的任何位置。
因此,使用像sprintf
和strlen
这样的字符串函数是一个坏主意。 如果确实需要使用第二个缓冲区( buffer
),则可以使用memcpy
。 您也可以直接读入r.payload(如果r.payload已经分配了足够的大小)。
您正在寻找二进制文件的fread
。 fread
的返回值告诉您已将多少字节读取到缓冲区中。
您也可以考虑再次致电fseek
。 请参阅此处如何获取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;
}
不,sprintf没有正确完成。 缓冲区溢出很容易发生,这是一个非常严重的安全问题。
我将考虑以例如1024字节的块而不是逐行发送文件,因此我将fgets调用替换为fread调用。
为什么要两次打开文件? 显然是要获取其大小,但是您只能打开一次,然后跳回到文件的开头。 而且,您没有将读取的尺寸用于任何事情。
它是二进制文件还是文本文件? fgets()假定您正在读取文本文件-它在换行符处停止-但您说这是一个二进制文件,并用“ rb”打开(实际上,第一次使用“ rt”打开它那是一个错字)。
IMO,您永远不要使用sprintf。 写入缓冲区的字符数取决于传入的参数,在这种情况下,如果缓冲区中没有'\\ 0',则无法预测将多少字节复制到r.payload,并且有一个您很有可能会溢出该缓冲区。
我认为sprintf()是第一要解决的问题。 使用memcpy(),您可以准确地告诉它要复制多少字节。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.