[英]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.