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

Posted

技术标签:

【中文标题】使用 C 将 .raw 文件数据存储为指针【英文标题】:Storing .raw File Data as a Pointer Using C 【发布时间】:2021-09-28 03:44:22 【问题描述】:

我正在尝试读取一个“.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;

【问题讨论】:

你可能想要filesize/2。也使用二进制模式 ("wb")。您还可以检查freadfwrite 是否返回任何错误。 感谢您的快速回复。使用filesize/2的目的是什么?每次我回信时,我的文件大小都会翻倍,所以我认为您正在做某事。 您搜索到文件的末尾以查看它有多大,然后尝试阅读它而不再次搜索。你认为从文件中读取了多少? 为什么使用uint16_t 在将输入文件搜索到末尾以获取其大小后,您不会在读取字节之前返回文件的开头。另外,不要使用magic numbers - fseek(image_raw, 0, SEEK_END);fseek(image_raw, 0, 2); 更容易理解 【参考方案1】:

你已经有了很好的答案和有用的 cmets

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

如果文件大小可能很奇怪,在最后一个字节/单词处做什么

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

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;

【讨论】:

【参考方案2】:

您的代码存在多个问题:

缺乏错误处理。

在查找输入文件以获取其大小后,不将其查找回偏移量 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;

【讨论】:

哇,这是一个很有帮助的答案。您的代码完全符合我的要求。非常感谢您花时间写出这篇文章,我肯定对文件操作有了更好的了解。

以上是关于使用 C 将 .raw 文件数据存储为指针的主要内容,如果未能解决你的问题,请参考以下文章

[swmm]调用存储数据的“结构指针数组”

SQL Server 数据存储:4 GB Raw,SQL Server 有多少?

C语言 如何给指针数组划分动态存储空间

将数据存储在 blob 中与存储指向文件的指针有啥区别?

使用 C/C++ 访问 RAW 磁盘

C指针及其运算