为什么fread没有正确读入uint16_t值?

时间:2016-01-27 21:32:25

标签: c fread

尝试从bmp文件中读取签名时,在调用fread后,sig包含52428请注意,这是0xCCCC而不是19778,这是0x4D42'BM'的正确十进制值,这是BMP文件的正确标头签名。

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

5 个答案:

答案 0 :(得分:1)

假设文件存在,您应该知道您将文件作为文本而不是二进制文件打开。

尝试:

FILE *f = fopen(file, "rb");

答案 1 :(得分:1)

我会尝试几件事:

  1. fread初始化为零。
  2. 检查char sig[2]; ... if ( 2 != fread(sig, 1, 2, f) ) { ... 的返回值以确保操作成功。
  3. 如果没有任何结果,接下来要尝试的是使用

    $('#table_id td').each(function() {
    if ($(this).text() == 'Mitch') {
        $(this).closest('td').css('background-color', '#f00');
     }
    });
    

答案 2 :(得分:0)

我测试了你的代码,我没有遇到任何问题。 你能提供你想要阅读的BMP文件吗?

此外,我已经为您编写了一些代码,可以帮助您在项目变得更大时保持一切井然有序。我建议将结构放入头文件中。

编辑:我必须自己定义结构中的数据类型,因为我在没有stdint.h的环境中这样做了。抱歉。但你可以改变它们。

您可以使用这些结构来存储标题信息:

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;

使用此功能读取标题

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);
}

使用main函数调用所有内容并处理错误

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);

答案 3 :(得分:0)

您的代码完全应该可以使用。您为sig分配2个字节,然后正确地从文件的开头读取2个字节。只要前两个字节是BM或' 0x4D42'那么你应该好。

我的猜测是问题出在您的目录/文件路径上。

检查以确保您传入的文件具有正确的文件路径。请注意,要使用相对文件路径传递它,您需要将文件路径设置为相对于项目的根目录。

希望这有帮助!

答案 4 :(得分:-1)

这是解决方案尝试理解它,随意问你是否有任何疑问。

请记住BMP的前两个字节应始终为'B'后跟' M'hex0x420x4D或{{1 }} int(8 bit)66

77

如果你想要bmp文件的int(8位)值,那么你可以添加以下代码行,

#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;
}