为什么 fread 没有正确读入 uint16_t 值?
Why does fread not read into uint16_t value properly?
当尝试从 bmp 文件中读取签名时,在调用 fread 后,sig
包含 52428
注意这是 0xCCCC
而不是 19778
,它0x4D42
或 'BM'
的正确十进制值是 BMP 文件的正确 header 签名。
uint16_t sig;
// 0. If any of the operations fail, free any memory and return 0
// 1. Open the file
FILE *f = fopen(file, "r");
if (f == 0) {
printf("Cannot open file\n");
}
// 2a. Read the initial fields of the header; verify that the file type (BM) is correct.
fseek(f, 0, SEEK_SET);
fread(&sig, sizeof(uint16_t), 1, f); // signature
printf("%d\n", sig);
if (sig != 0x4D42) {
printf("not a bmp file!\n");
return 0;
}
我尝试使用 uint8_t 以及许多其他解决此问题的解决方案一次读取一个字节。
似乎 fread
只是没有正确写入 sig
,因为 CC
是使用我正在使用的编译器的未初始化内存的默认格式。任何帮助将不胜感激。
这是我试图读入的 bmp 文件:
image
假设文件存在,您应该知道您打开的是文本文件,而不是二进制文件。
尝试:
FILE *f = fopen(file, "rb");
我会尝试一些事情:
- 将
sig
初始化为零。
- 检查
fread
的 return 值以确保操作成功。
如果没有结果,接下来要尝试的是使用
char sig[2];
...
if ( 2 != fread(sig, 1, 2, f) ) { ...
我测试了你的代码,没有问题。
能提供一下你要阅读的BMP文件吗?
另外,我在这里为您编写了一些代码,如果项目变得更大,这些代码可能会帮助您保持一切井井有条。我建议将结构放入 header 文件中。
编辑:必须自己在结构中定义数据类型,因为我是在没有 stdint.h
的环境中这样做的。对不起。但是你可以改变它们。
您可以使用这些结构来存储您的 header 信息:
typedef struct {
uint16 Signature;
uint32 Size;
uint16 Reserved1;
uint16 Reserved2;
uint32 BitsOffset;
} BITMAP_FILE_HEADER;
typedef struct {
uint32 biSize;
int32 biWidth;
int32 biHeight;
uint16 biPlanes;
uint16 biBitCount;
uint32 biCompression;
uint32 biSizeImage;
int32 biXPelsPerMeter;
int32 biYPelsPerMeter;
uint32 biClrUsed;
uint32 biClrImportant;
} BITMAP_INFO_HEADER;
typedef struct {
uint32 bcSize;
uint16 bcWidth;
uint16 bcHeight;
uint16 bcPlanes;
uint16 bcBitCount;
} BITMAP_CORE_HEADER;
使用此函数读取header
int read_header(FILE* inputfile, BITMAP_INFO_HEADER* header, BITMAP_FILE_HEADER* fHeader) {
BITMAP_FILE_HEADER fileHeader;
BITMAP_INFO_HEADER infoHeader;
BITMAP_CORE_HEADER coreHeader;
uint32 headersize;
fread(&fileHeader.Signature, sizeof(fileHeader.Signature), 1, inputfile);
printf("%d", fileHeader.Signature);
}
并使用主函数调用所有内容并处理错误
int main(void) {
FILE* inputfile = NULL;
BITMAP_INFO_HEADER infoHeader = {0};
BITMAP_FILE_HEADER fileHeader = {0};
if ( (inputfile = fopen("source.bmp", "rb")) == NULL ) {
ERROR("can't open file.")
return 1;
}
if ( read_header(inputfile, &infoHeader, &fileHeader) == 0 ) {
ERROR("Fileformat not supported.")
return 1;
}
}
根据您分配的内容,您可以使用 ERROR()
宏来清除所有内容,例如:
#define ERROR(ErrMsg) \
printf("Error: %s\n", ErrMsg); \
if (bitmapData != NULL) \
free(bitmapData); \
if (yourAlloc != NULL) \
free(yourAlloc);
这里是解法试着理解一下,有什么疑问欢迎追问。
记住 BMP 的前两个字节应该总是 'B'
后跟 'M'
或 hex
值 0x42
和 0x4D
或 int(8 bit)
值 66
和 77
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp = NULL;
int fsize,result;
char *buffer = NULL;
fp = fopen("fileName.bmp", "rb+");
if (fp == NULL)
{
printf( "Error! File Not found!\n");
}
else
{
fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
printf("File Size:%d\n",fsize);
buffer = malloc(sizeof(char)*fsize);
result=fread(buffer, sizeof(char), fsize, fp);
if (result != fsize)
{
printf("Error Reading file!\n");
}
fclose(fp);
}
//Remember the first two bytes of BMP Should always be
//'B' followed 'M' or hex values 0x42 and 0x4D or int(8 bit) values 66 and 77
if (buffer[0] == 'B' && buffer[1] == 'M')
{
printf("File is BMP!\n");
}
else
{
printf("Not BMP!\n");
}
free(buffer);
buffer = NULL;
return 0;
}
如果你想要 bmp 文件的 int(8 位)值,那么你可以添加以下代码行,
char *buffer = NULL;
int *fdata = NULL;
//Get the file size as in above code and after that
buffer = malloc(sizeof(char)*fsize);
fdata = malloc(sizeof(int)*fsize);
result=fread(buffer, sizeof(char), fsize, fp);
if (result != fsize)
{
printf("Error Reading file!\n");
}
for (int i = 0; i < fsize; i++)
{
if (buffer[i] < 0)
{
fdata[i] = 256 + (int)buffer[i];
}
else
{
fdata[i] = (int)buffer[i];
}
}
for (int i = 0; i < fsize; i++)
{
printf("%d ",fdata[i]);
}
//free up after your done
free(buffer);
buffer=NULL;
free(fdata);
fdata=NULL;
您的代码应该完全可以工作。您正在为 sig
分配 2 个字节,然后从文件开头正确读取 2 个字节。只要前两个字节是 BM
或 '0x4D42' 就可以了。
我的猜测是问题出在您的 directory/file 路径上。
检查以确保您传入的文件具有正确的文件路径。请注意,要使用相对文件路径传递它,您需要使文件路径相对于项目的根目录。
希望对您有所帮助!
当尝试从 bmp 文件中读取签名时,在调用 fread 后,sig
包含 52428
注意这是 0xCCCC
而不是 19778
,它0x4D42
或 'BM'
的正确十进制值是 BMP 文件的正确 header 签名。
uint16_t sig;
// 0. If any of the operations fail, free any memory and return 0
// 1. Open the file
FILE *f = fopen(file, "r");
if (f == 0) {
printf("Cannot open file\n");
}
// 2a. Read the initial fields of the header; verify that the file type (BM) is correct.
fseek(f, 0, SEEK_SET);
fread(&sig, sizeof(uint16_t), 1, f); // signature
printf("%d\n", sig);
if (sig != 0x4D42) {
printf("not a bmp file!\n");
return 0;
}
我尝试使用 uint8_t 以及许多其他解决此问题的解决方案一次读取一个字节。
似乎 fread
只是没有正确写入 sig
,因为 CC
是使用我正在使用的编译器的未初始化内存的默认格式。任何帮助将不胜感激。
这是我试图读入的 bmp 文件: image
假设文件存在,您应该知道您打开的是文本文件,而不是二进制文件。
尝试:
FILE *f = fopen(file, "rb");
我会尝试一些事情:
- 将
sig
初始化为零。 - 检查
fread
的 return 值以确保操作成功。
如果没有结果,接下来要尝试的是使用
char sig[2];
...
if ( 2 != fread(sig, 1, 2, f) ) { ...
我测试了你的代码,没有问题。 能提供一下你要阅读的BMP文件吗?
另外,我在这里为您编写了一些代码,如果项目变得更大,这些代码可能会帮助您保持一切井井有条。我建议将结构放入 header 文件中。
编辑:必须自己在结构中定义数据类型,因为我是在没有 stdint.h
的环境中这样做的。对不起。但是你可以改变它们。
您可以使用这些结构来存储您的 header 信息:
typedef struct {
uint16 Signature;
uint32 Size;
uint16 Reserved1;
uint16 Reserved2;
uint32 BitsOffset;
} BITMAP_FILE_HEADER;
typedef struct {
uint32 biSize;
int32 biWidth;
int32 biHeight;
uint16 biPlanes;
uint16 biBitCount;
uint32 biCompression;
uint32 biSizeImage;
int32 biXPelsPerMeter;
int32 biYPelsPerMeter;
uint32 biClrUsed;
uint32 biClrImportant;
} BITMAP_INFO_HEADER;
typedef struct {
uint32 bcSize;
uint16 bcWidth;
uint16 bcHeight;
uint16 bcPlanes;
uint16 bcBitCount;
} BITMAP_CORE_HEADER;
使用此函数读取header
int read_header(FILE* inputfile, BITMAP_INFO_HEADER* header, BITMAP_FILE_HEADER* fHeader) {
BITMAP_FILE_HEADER fileHeader;
BITMAP_INFO_HEADER infoHeader;
BITMAP_CORE_HEADER coreHeader;
uint32 headersize;
fread(&fileHeader.Signature, sizeof(fileHeader.Signature), 1, inputfile);
printf("%d", fileHeader.Signature);
}
并使用主函数调用所有内容并处理错误
int main(void) {
FILE* inputfile = NULL;
BITMAP_INFO_HEADER infoHeader = {0};
BITMAP_FILE_HEADER fileHeader = {0};
if ( (inputfile = fopen("source.bmp", "rb")) == NULL ) {
ERROR("can't open file.")
return 1;
}
if ( read_header(inputfile, &infoHeader, &fileHeader) == 0 ) {
ERROR("Fileformat not supported.")
return 1;
}
}
根据您分配的内容,您可以使用 ERROR()
宏来清除所有内容,例如:
#define ERROR(ErrMsg) \
printf("Error: %s\n", ErrMsg); \
if (bitmapData != NULL) \
free(bitmapData); \
if (yourAlloc != NULL) \
free(yourAlloc);
这里是解法试着理解一下,有什么疑问欢迎追问。
记住 BMP 的前两个字节应该总是 'B'
后跟 'M'
或 hex
值 0x42
和 0x4D
或 int(8 bit)
值 66
和 77
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp = NULL;
int fsize,result;
char *buffer = NULL;
fp = fopen("fileName.bmp", "rb+");
if (fp == NULL)
{
printf( "Error! File Not found!\n");
}
else
{
fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
printf("File Size:%d\n",fsize);
buffer = malloc(sizeof(char)*fsize);
result=fread(buffer, sizeof(char), fsize, fp);
if (result != fsize)
{
printf("Error Reading file!\n");
}
fclose(fp);
}
//Remember the first two bytes of BMP Should always be
//'B' followed 'M' or hex values 0x42 and 0x4D or int(8 bit) values 66 and 77
if (buffer[0] == 'B' && buffer[1] == 'M')
{
printf("File is BMP!\n");
}
else
{
printf("Not BMP!\n");
}
free(buffer);
buffer = NULL;
return 0;
}
如果你想要 bmp 文件的 int(8 位)值,那么你可以添加以下代码行,
char *buffer = NULL;
int *fdata = NULL;
//Get the file size as in above code and after that
buffer = malloc(sizeof(char)*fsize);
fdata = malloc(sizeof(int)*fsize);
result=fread(buffer, sizeof(char), fsize, fp);
if (result != fsize)
{
printf("Error Reading file!\n");
}
for (int i = 0; i < fsize; i++)
{
if (buffer[i] < 0)
{
fdata[i] = 256 + (int)buffer[i];
}
else
{
fdata[i] = (int)buffer[i];
}
}
for (int i = 0; i < fsize; i++)
{
printf("%d ",fdata[i]);
}
//free up after your done
free(buffer);
buffer=NULL;
free(fdata);
fdata=NULL;
您的代码应该完全可以工作。您正在为 sig
分配 2 个字节,然后从文件开头正确读取 2 个字节。只要前两个字节是 BM
或 '0x4D42' 就可以了。
我的猜测是问题出在您的 directory/file 路径上。
检查以确保您传入的文件具有正确的文件路径。请注意,要使用相对文件路径传递它,您需要使文件路径相对于项目的根目录。
希望对您有所帮助!