在C中读取大bin文件〜2mb

问题描述

我想读取大小小于2mb的bin文件

此刻,我用于读取bin文件代码如下:

编辑:

#define MAX_BYTES_IN_FILE 500000         // ~ 2mb
#define ERROR_FILE 1

int get_byte_from_file(FILE *stream,unsigned char *dataarray) {
    int counter = 0;
                               
    while ((dataarray[counter] = fgetc(stream)) != EOF) {
        counter += 1;
    }
    return counter;
}

函数示例使用的Main看起来像这样。

int main(int argc,char **argv) {
    FILE *datei;
   
    unsigned int number_of_bytes;
    unsigned char *dataarray;

    dataarray = (unsigned char *)malloc(sizeof(unsigned char) * MAX_BYTES_IN_FILE);

    datei = fopen(argv[1],"rb");
   
    number_of_bytes = get_byte_from_file(datei,dataarray);
   
    for (int i = 0; i < number_of_bytes; i++)
        printf("%x ",dataarray[i]);
   
    return 0;
}

也许我犯了一个简单的错误,但看不到该错误仍然是:Segmentation fault (core dumped)

解决方法

此行足以使您的程序崩溃:

while ((dataarray[counter] = fgetc(stream)) != EOF) {

让我们逐步进行操作:

  1. fgetc(stream)读取一个字节并返回其值或EOF。由于一个字节可以有任何可能的值,因此fgetc()返回一个较大的int,该值可以容纳一个EOF值,该值不同于在文件中可能找到的任何字节值。>

  2. 您将此int值分配给unsigned charEOF值将被截断为此数据类型。

  3. 分配的值的类型为unsigned char,并且转换后的EOF的值不再等于EOF。因此,比较总是失败,并且您的程序将继续获取数据,直到缓冲区溢出并开始发生讨厌的事情为止。

您需要将fgetc()的结果存储在int变量中,直到您检查它的确不是EOF值。

,

也许是这样。

void *readfile(FILE *fi,long *filesize)
{
    void *buff;
    fseek(fi,SEEK_END);
    *filesize = ftell(fi);
    fseek(fi,SEEK_SET);
    buff = malloc(*filesize);
    if(buff)
    {
        fread(buff,1,*filesize,fi);
    }
    return buff;
}

您需要添加错误检查-我不是,因为这仅仅是个主意。

您的用法:

int main(int argc,char **argv) {
 
   FILE *datei;
   
   long number_of_bytes;
   unsigned char *dataarray;

   datei=fopen(argv[1],"rb");
   
   dataarray = readfile(datei,&number_of_bytes);
   
   for (int i=0;dataarray && i<number_of_bytes;i++)
       printf("%hhx ",dataarray[i]);
   
   return 0;
}
,

出现分段错误的原因是分配不正确:您分配了MAX_BYTES_IN_FILE个字节而不是unsigned int个元素。分配后,该数组仅包含MAX_BYTES_IN_FILE / sizeof(unsigned int)个元素,而文件的长度可能为MAX_BYTES_IN_FILE * sizeof(unsigned int)个字节。

您正在从文件读取字节(值在0255之间),但是您使用了unsigned int元素。逻辑是什么?文件包含32位值还是单个字节?

一旦您可以确认文件内容与数组在内存中的表示形式完全相同,就可以使用fread()在一次调用中读取整个文件。