使用 C 将 .raw 文件数据存储为指针

Storing .raw File Data as a Pointer Using C

我正在尝试读取一个“.raw”文件,该文件存储了使用 C 在相机上拍摄的图像的内容。我想将这些内容存储到 uint16_t * 中。 在下面的代码中,我尝试使用 fread() 将此数据存储到指针中,然后使用 fwrite() 将此数据写入测试文件以检查我的数据是否正确。 但是,当我写回文件时,我检查它时完全是黑色的。

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

#define MAX_ROW 2560
#define MAX_COL 2160

int main()
{
    char filename[32] = "image1.raw";
    FILE * image_raw = fopen(filename, "rb");
    fseek(image_raw, 0, 2);
    long filesize = ftell(image_raw);
    
    /*READ IMAGE DATA*/
    uint16_t * image_data_ptr;
    image_data_ptr = (uint16_t *)malloc(sizeof(uint16_t)*MAX_ROW*MAX_COL);
    fread(image_data_ptr, sizeof(uint16_t), filesize, image_raw);
    fclose(image_raw);
   
   
    /*TEST WRITING THE SAME DATA BACK INTO TEST RAW FILE*/
    FILE *fp;
    fp = fopen("TEST.raw", "w");
    fwrite(image_data_ptr, sizeof(uint16_t), filesize, fp);
    fclose(fp);
    
    return 0;
}

您的代码存在多个问题:

  • 缺乏错误处理。

  • 在查找输入文件以获取其大小后,未将输入文件查找回偏移量 0。考虑使用 stat() 或等效方法来获取文件大小,而无需搜索文件。

  • 从输入文件读取或写入输出文件时,
  • 不将 filesize 除以 sizeof(uint16_t)filesize 以字节表示,但 fread/fwrite 以给定大小的项目数表示,而您的项目大小不是 1 个字节。

  • 没有以二进制模式打开输出文件。

  • 泄漏您分配的缓冲区。

话虽如此,请尝试更像这样的东西:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

int main()
{
    char filename[32] = "image1.raw";

    FILE *image_raw = fopen(filename, "rb");
    if (!image_raw) {
        fprintf(stderr, "Can't open input file\n");
        return -1;
    }

    if (fseek(image_raw, 0, SEEK_END) != 0) {
        fprintf(stderr, "Can't seek input file\n");
        fclose(image_raw);
        return -1;
    }

    long filesize = ftell(image_raw);
    if (filesize == -1L) {
        fprintf(stderr, "Can't get input file size\n");
        fclose(image_raw);
        return -1;
    }

    rewind(image_raw);

    long numSamples = filesize / sizeof(uint16_t);

    /*READ IMAGE DATA*/
    uint16_t *image_data_ptr = (uint16_t*) malloc(filesize);
    if (!image_data_ptr) {
        fprintf(stderr, "Can't allocate memory\n");
        fclose(image_raw);
        return -1;
    }

    size_t numRead = fread(image_data_ptr, sizeof(uint16_t), numSamples, image_raw);
    if (numRead != numSamples) {
        fprintf(stderr, "Can't read samples from file\n");
        free(image_data_ptr);
        fclose(image_raw);
        return -1;
    }

    fclose(image_raw);
   

    /*TEST WRITING THE SAME DATA BACK INTO TEST RAW FILE*/
    FILE *fp = fopen("TEST.raw", "wb");
    if (!fp) {
        fprintf(stderr, "Can't open output file\n");
        free(image_data_ptr);
        return -1;
    }

    if (fwrite(image_data_ptr, sizeof(uint16_t), numSamples, fp) != numSamples) {
        fprintf(stderr, "Can't write to output file\n");
        fclose(fp);
        free(image_data_ptr);
        return -1;
    }

    fclose(fp);
    free(image_data_ptr);
    
    return 0;
}

您已经有了很好的回答和有用的评论

无论如何,考虑一下如果你想迭代你的文件,作为一个整体加载到内存中,作为 unsigned wordsarray:

  • 如果文件大小可能是奇数最后怎么办 byte/word

  • 在确定文件大小后,您可以在一次调用中读取整个文件

  • fstat()是获取文件大小的正常方式

  • 从命令行获取文件名作为参数比重新编译程序或更改文件名以使用程序要灵活得多

下面的代码就是这样做的:

  • 使用 image.raw 作为文件名的默认值,但允许您在命令行中输入文件名
  • 使用fstat()获取文件大小
  • 使用单个 fread() 调用将整个文件作为单个记录读取

使用原始程序文件作为输入的测试:


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        20/07/2021     17:40           1067 main.c   
                                                                                                                                                   
PS > gcc -Wall -o tst main.c
PS > ./tst main.c
File is "main.c". Size is 1067 bytes
File "main.c" loaded in memory.
PS > ./tst xys
File is "xys". Could not open: No such file or directory

C 示例

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

int main(int argc, char**argv)
{
    const char* default_file = "image.raw";
    char    f_name[256];
    if (argc < 2)
        strcpy(f_name, default_file);
    else
        strcpy(f_name, argv[1]);

    FILE* F = fopen(f_name, "rb");
    if (F == NULL)
    {
        printf("File is \"%s\". ", f_name);
        perror("Could not open");
        return -1;       
    }
    struct stat info;
    fstat(_fileno(F),&info);
    printf("File is \"%s\". Size is %lu bytes\n", f_name, info.st_size);

    uint16_t* image = malloc(info.st_size);
    if (image == NULL)
    {   perror("malloc() error");
        return -2;
    };

    if (fread(image, info.st_size, 1, F) != 1)
    {   perror("read error");
        free(image);
        return -3;
    };

    // use 'image'
    printf("File \"%s\" loaded in memory.\n", f_name);
    free(image);
    fclose(F);
    return 0;
}