[英]Reading content from .bin file in C Error on first fread value
我的 fread function 遇到了一些问题。 一切都很好,但我的错误检查器在 fread 的第一个值上关闭,我完全不知道为什么。
如果我已经倒回到文件的开头,并且它正确打印了我的值,那么什么失败了?
int main()
{
FILE *BinFile;
//FILE *CopyBinFile;
// printf("Enter name of a file you wish to see\n");
//gets(file_name);
if ((BinFile = fopen("C:/Users/Tom/OneDrive/Desktop/out.bin","rb")) == NULL){
printf("Error, shits broke");
exit(1);
}
fseek(BinFile,0,SEEK_END);
SizeofFile = ftell(BinFile);
printf("The contents of out.bin file are:\n");
printf("the size of the file is %d \n", SizeofFile);
//fseek(BinFile,0,SEEK_SET ); // point back to the start
rewind(BinFile);
if (fread(&Buffer4Can, sizeof(uint8_t) , SizeofFile ,BinFile) != 1){ //**<<<<--- this**
printf("err \n");
}
for(c=0;c<SizeofFile;c++){
printf("%02X ", Buffer4Can[c]);
count++;
if (count == 8){
printf(" \n");
count =0;
}
}
return 0;
}
更新:@感谢大家的帮助。 我真的很感激。 能够很好地将它移植到 stmIDE 并且更容易,因为它在 st 提供的库中似乎更加精简
if ( f_mount(&MyFatFs, SDPath, 1)== FR_OK){
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12); //
if( f_open(&myFILE, "out.bin", FA_READ) == FR_OK ){
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_13); //ORANGE
}
// get byte amount from file
//f_lseek(&myFILE, 0x20);
SizeofFile=f_size(&myFILE);
//f_rewind(&myFILE);
//SizeofFile=11240;
//store data into buffer
if (f_read(&myFILE, &Buffer4Can, SizeofFile, &byteCounter)== FR_OK){
}
HAL_Delay(2000);
//toggle
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_14);
//untoggle
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_13); //orng led
}
if(byteCounter==0){ /* error or eof */
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15); // blue LED
}
您有许多细微的错误,然后正在检查fread
的返回值是否不正确。 在您对fread
的调用中,不需要在Buffer4Can
之前加上&
(的地址)运算符。 Buffer4Can
是一个数组,将在访问时转换为指向第一个元素的指针(请参阅: C11 标准 - 6.3.2.1 其他操作数 - 左值、arrays 和 function 指示符(p3) )
当您获取Buffer4Can
的地址时,您可以将提供的指针类型从fread
uint8_t*
(不带&
)更改为uint8_t (*)[120000)
(使用&
,类型变为指向数组的uint8_t[120000]
)。 巧合的是, Buffer4Can
是一个数组,指向uint8_t
的指针和指向uint8_t[120000]
的 *pointer-to-array-都将解析到相同的地址(但类型截然不同)。
由于它们解析到相同的地址,并且由于fread()
将void*
参数作为其第一个参数,因此错误会默默地被忽视。 (如果您尝试fread (&Buffer4Can + 1, ...
事情不会顺利...)
@Domenic 指出的另一个问题是您对fread()
返回的比较。 fread()
的原型是:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
fread()
的返回值为:
On success, fread() and fwrite() return the number of items read or written. This number equals the number of bytes transferred only when size is 1.
在您的情况下,您为 function 的size
参数提供sizeof(uint8_t)
,这意味着在您的情况下返回"This number equals the number of bytes transferred"
或SizeofFile
。 此外,就像sizeof (char)
, sizeof (uint8_t)
是1
所以它可以简单地表示为1
。
您缺少验证的唯一其他区域是在fread()
之前,您必须确认SizeofFile <= 120000
以保护您的数组边界。 您可以将其与对fread()
的调用放在一起:
if (MAXB < SizeofFile || /* protect bounds/compare return to SizeofFile */
fread (Buffer4Can, 1, SizeofFile, fp) != (size_t)SizeofFile) {
fputs ("error: file exceeds buffer size, or fread failed.\n", stderr);
return 1;
}
(注意: fread()
的返回类型是size_t
,因此需要转换SizeofFile
以避免有符号和无符号值之间的比较)
使用精确宽度类型时,用于输入和 output 转换的宏在inttypes.h
中提供(包括stdint.h
本身) 十六进制格式的unit8_t
值的 output 的宏是PRIx8
。 对于 output 8 个 2-char hex-values 每行以"0x"
,您可以执行以下操作:
for (int i = 0; i < (int)SizeofFile; i++) { /* loop over bytes */
if (i && i % 8 == 0) /* output 8 per-line */
putchar ('\n');
printf (" 0x%02" PRIx8, Buffer4Can[i]); /* use exact width specier */
}
putchar ('\n'); /* tidy up with newline */
(注意: PRIx8
宏不在格式字符串的引用部分内,它是独立的。如果您想要在末尾换行,格式字符串将是" 0x%02" PRIx8 "\n"
)
有了这个,您应该根据需要编程 function。 请注意,它将文件名作为程序的第一个参数读取,或者如果没有提供,则默认情况下将从stdin
读取(您可以在stdin
上重定向二进制文件)。 总而言之,您可以执行以下操作:
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#define MAXB 120000 /* if you need a constant, #define one (or more) */
int main (int argc, char **argv) {
uint8_t Buffer4Can[MAXB]; /* buffer to hold bytes from file */
long SizeofFile; /* size of file (note type long for ftell) */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "rb") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
fseek (fp, 0, SEEK_END); /* seek end */
SizeofFile = ftell(fp); /* get lenght */
rewind (fp); /* rewind to beginning */
if (MAXB < SizeofFile || /* protect bounds/compare return to SizeofFile */
fread (Buffer4Can, 1, SizeofFile, fp) != (size_t)SizeofFile) {
fputs ("error: file exceeds buffer size, or fread failed.\n", stderr);
return 1;
}
if (fp != stdin) /* close file if not stdin */
fclose (fp);
for (int i = 0; i < (int)SizeofFile; i++) { /* loop over bytes */
if (i && i % 8 == 0) /* output 8 per-line */
putchar ('\n');
printf (" 0x%02" PRIx8, Buffer4Can[i]); /* use exact width specier */
}
putchar ('\n'); /* tidy up with newline */
}
(注意:所有多余的变量都已删除,注意ftell()
的返回类型是long
,而不是int
)
如果您还有其他问题,请仔细查看并告诉我。
关于:
if (fread(&Buffer4Can, sizeof(uint8_t), SizeofFile ,BinFile) != 1)
缓冲区Buffer4Can
是一个数组名称,它引用了一个降级为数组第一个字节地址的“裸”数组名称。 因此,在前面加上&
是一个错误。
参数也有问题: SizeofFile
因为 function 需要一个size_t
类型的参数。 建议:
if (fread(Buffer4Can, sizeof(uint8_t), (size_t)SizeofFile, BinFile ) != (size_t)SizeofFile)
fread()
function 返回读取的“项目”数。 在当前语句中,每一项的大小都是1
,所以一个成功的读取操作会返回第三个参数,所以应该比较(size_t)SizeofFile
而不是将返回的值与1
进行比较
从fread()
的 MAN 页面
成功时, fread() 和 fwrite() 返回读取或写入的项目数。 此数字等于仅当 size 为 1 时传输的字节数。如果发生错误或到达文件末尾,则返回值是一个短项计数(或零)。
请注意返回的类型和参数类型,并给函数他们所期望的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.