C语言二进制文件读写以及大小端转换

来源:互联网 发布:java常用集合类 编辑:程序博客网 时间:2024/05/13 05:27

因为工作需要所以需要将文件用二进制方式读取。网上资料比较少,所以我再次把自己的实践过程mark一下。
并且由于代码可能需要在不同的机器上运行,所以还需要考虑一下大小端转换问题。
先看下面的代码,然后我在简短的解释一下。

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <string>#define nmemb 7/****************************************************  Date types(Compiler specific) 数据类型(和编译器相关)*****************************************************/typedef unsigned char uint8;      /* Unsigned 8 bit quantity  */typedef signed char int8;         /* Signed 8 bit quantity    */typedef unsigned short uint16;    /* Unsigned 16 bit quantity */typedef signed short int16;       /* Signed 16 bit quantity   */typedef unsigned int uint32;      /* Unsigned 32 bit quantity */typedef signed int int32;         /* Signed 32 bit quantity   */typedef float fp32;               /* Single precision         */                                  /* floating point           */typedef double fp64;              /* Double precision         */                                  /* floating point           *///int32#define BigtoLittle32(A)   ((( (uint32)(A) & 0xff000000 ) >> 24) | \                                               (( (uint32)(A) & 0x00ff0000 ) >> 8)   | \                                               (( (uint32)(A) & 0x0000ff00 ) << 8)   | \                                               (( (uint32)(A) & 0x000000ff ) << 24))//int16#define BigtoLittle16(A)   (( ((uint16)(A) & 0xff00) >> 8 )    | \                            (( (uint16)(A) & 0x00ff ) << 8))/*************************************************************     Conversion little endian float data to big endian*     *************************************************************/float ReverseFloat(const float inFloat){    float retVal;    char *floatToConvert = (char*) & inFloat;    char *returnFloat = (char*) & retVal;    // swap the bytes into a temporary buffer    returnFloat[0] = floatToConvert[3];    returnFloat[1] = floatToConvert[2];    returnFloat[2] = floatToConvert[1];    returnFloat[3] = floatToConvert[0];    return retVal;}struct matrix{    int row;    int column;}s[nmemb];void set_s(int j, int x, int y){    s[j].row = x;    s[j].column = y;}bool is_bigendian(){    int a = 0x1234;    char b =  *(char *)&a;  //b == the Low address part of a    //printf("%c\n", b);    if (b == 0x34) {        return false;    }    return true;}int main(){    if (is_bigendian()) {        printf("BigEndian\n");    } else {        printf("LittleEndian\n");    }    FILE *fp;    set_s(0, 1, 50);    set_s(1, 1, 80);    set_s(2, 4, 20);    set_s(3, 50, 1);    set_s(4, 80, 2);    set_s(5, 100, 3);    set_s(6, 100, 4);    int ans = sizeof(struct matrix);    printf("size: %d\n", ans);    printf("size: %d\n", sizeof(s));    if ((fp = fopen("test", "wb")) == NULL) {        printf("EROOR\n");        return 1;    }    for (int j = 0; j < nmemb; ++j) {        printf("row: %d   column: %d\n", s[j].row, s[j].column);    }    fwrite(s, sizeof(struct matrix), nmemb, fp);    for (int i = 0; i < nmemb; ++i) {        float *m = (float*) malloc(sizeof(float) * s[i].row * s[i].column);        bzero(m, sizeof(float) * s[i].row * s[i].column);        for (int j = 0; j < s[i].row; ++j) {            for (int k = 0; k < s[i].column; ++k) {                m[k + j*s[i].column] = k;            }        }        fwrite(m, sizeof(float), s[i].row * s[i].column, fp);        free(m);    }    fclose(fp);    printf("11\n");    /*    printf("%d\n", sizeof(float));    FILE *fp;    if ((fp = fopen("test", "rb")) == NULL) {        printf("EROOR\n");        return 1;    }    fread(s, sizeof(struct matrix), nmemb, fp);    for (int i = 0; i < nmemb; ++i) {        printf("row: %d   column: %d\n", s[i].row, s[i].column);    }    for (int i = 0; i < nmemb; ++i) {        float *m = (float*) malloc(sizeof(float) * s[i].row * s[i].column);        bzero(m, sizeof(float) * s[i].row * s[i].column);        fread(m, sizeof(float), s[i].row * s[i].column, fp);        for (int j = 0; j < s[i].row; ++j) {            for (int k = 0; k < s[i].column; ++k) {                printf("%lf ", m[k + j*s[i].column]);            }            printf("\n");        }        printf("\n\n");        free(m);    }    fclose(fp);    */    return 0;}

fopen和fclose是很常见的,在这里就不做解释了。我们来看看fwrite和fread,本来以为这个很麻烦,但是用过之后发现这个二进制文件读写才是最简单的。

size_t fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream);
fwrite()用来将数据写入文件流中。
stream为已打开的文件指针
ptr 指向欲写入的数据地址
写入的字符数以参数size*nmemb来决定。
size表示写入一个nmemb的内存大小。
fwrite()会返回实际写入的nmemb数目。

size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream);
fread()用来从文件流中读取数据。
stream为已打开的文件指针
ptr 指向欲存放读取进来的数据空间
读取的字符数以参数size*nmemb来决定
size表示读取一个nmemb的内存大小。
fread()会返回实际读取到的nmemb数目,如果此值比参数nmemb 小,则代表可能读到了文件尾或有错误发生,这时必须用feof()或ferror()来决定发生什么情况。
返回实际读取到的nmemb数目。

详情参见上面的代码。

另外就是大小端的问题了。关于大小端的具体解释网上有很多,在此不作解释。参考上面写的代码,我判断了自己机器是大端还是小端,并且实现了int16,int32已经float数据类型的大小端转换,大端转小端,在使用相同的代码一次小端又变成了大端。

PS:float的大小端转化我之前一直以为写的是错的,因为好多数据转化之后输出都是0。后来发现可能是与float类型在内存中的存放有关,我们的程序是对的。

下面是写的比较详细的二进制读和写的函数。包括数值类型,struct,char*等的读写。

bool save_binary(char* file_path){    FILE *fp;    if ((fp = fopen(file_path, "wb")) == NULL) {        printf("EROOR\n");        return false;    }    fwrite(&vocab_total_size, sizeof(int), 1, fp);    FILE *fp1;    if ((fp1 = fopen("../out/vocab", "r")) == NULL) {        printf("No vocab file!\n");        return false;    }    char str[100];    int coun = 0;    while ((fscanf(fp1, "%s", str)) != EOF) {        int len = strlen(str);    coun++;    printf("%d %d %s\n", coun, len, str);    fwrite(&len, sizeof(int), 1, fp);    fwrite(str, sizeof(char), len, fp);    }    fclose(fp1);    //binary head, save the row and column of the matrixs    struct matrix    {        int row;        int column;    }s[NMEMB];    s[0].row = vocab_total_size; s[0].column = projection_size;    s[1].row = projection_size; s[1].column = hidden_size*4;    s[2].row = 1; s[2].column = hidden_size;    s[3].row = 1; s[3].column = hidden_size;    s[4].row = 1; s[4].column = hidden_size;    s[5].row = hidden_size; s[5].column = hidden_size*4;    s[6].row = hidden_size; s[6].column = punc_total_size;    s[7].row = vocab_total_size; s[7].column = projection_size;    s[8].row = projection_size; s[8].column = hidden_size*4;    s[9].row = 1; s[9].column = hidden_size;    s[10].row = 1; s[10].column = hidden_size;    s[11].row = 1; s[11].column = hidden_size;    s[12].row = hidden_size; s[12].column = hidden_size*4;    s[13].row = hidden_size; s[13].column = punc_total_size;    fwrite(s, sizeof(struct matrix), NMEMB, fp);    fwrite(final_We, sizeof(float), s[0].row * s[0].column, fp);    fwrite(final_W, sizeof(float), s[1].row * s[1].column, fp);    fwrite(final_Wip, sizeof(float), s[2].row * s[2].column, fp);    fwrite(final_Wfp, sizeof(float), s[3].row * s[3].column, fp);    fwrite(final_Wop, sizeof(float), s[4].row * s[4].column, fp);    fwrite(final_Wr, sizeof(float), s[5].row * s[5].column, fp);    fwrite(final_Wy, sizeof(float), s[6].row * s[6].column, fp);    fwrite(final_We_hg, sizeof(float), s[7].row * s[7].column, fp);    fwrite(final_W_hg, sizeof(float), s[8].row * s[8].column, fp);    fwrite(final_Wip_hg, sizeof(float), s[9].row * s[9].column, fp);    fwrite(final_Wfp_hg, sizeof(float), s[10].row * s[10].column, fp);    fwrite(final_Wop_hg, sizeof(float), s[11].row * s[11].column, fp);    fwrite(final_Wr_hg, sizeof(float), s[12].row * s[12].column, fp);    fwrite(final_Wy_hg, sizeof(float), s[13].row * s[13].column, fp);    fclose(fp);    return true;}
bool load_binary(char *file_path){    FILE *fp;    if ((fp = fopen(file_path, "rb")) == NULL) {        printf("EROOR\n");        return false;    }    int vocab_size;    fread(&vocab_size, sizeof(int), 1, fp);    printf("%d\n", vocab_size);    int coun = 0;    for (int j = 0; j < vocab_size; ++j) {        int len;        coun++;        fread(&len, sizeof(int), 1, fp);        char str[100];        fread(str, sizeof(char), len, fp);        str[len] = '\0';    //一定要加,不加出错    }    printf("%d\n", coun);    struct matrix    {        int row;        int column;    }s[NMEMB];    fread(s, sizeof(struct matrix), NMEMB, fp);    for (int i = 0; i < NMEMB; ++i) {        printf("row: %d   column: %d\n", s[i].row, s[i].column);    }    fread(We, sizeof(float), s[0].row * s[0].column, fp);    fread(W, sizeof(float), s[1].row * s[1].column, fp);    fread(Wip, sizeof(float), s[2].row * s[2].column, fp);    fread(Wfp, sizeof(float), s[3].row * s[3].column, fp);    fread(Wop, sizeof(float), s[4].row * s[4].column, fp);    fread(Wr, sizeof(float), s[5].row * s[5].column, fp);    fread(Wy, sizeof(float), s[6].row * s[6].column, fp);    fread(We_hg, sizeof(float), s[7].row * s[7].column, fp);    fread(W_hg, sizeof(float), s[8].row * s[8].column, fp);    fread(Wip_hg, sizeof(float), s[9].row * s[9].column, fp);    fread(Wfp_hg, sizeof(float), s[10].row * s[10].column, fp);    fread(Wop_hg, sizeof(float), s[11].row * s[11].column, fp);    fread(Wr_hg, sizeof(float), s[12].row * s[12].column, fp);    fread(Wy_hg, sizeof(float), s[13].row * s[13].column, fp);    fclose(fp);    for (int j = 0; j < s[3].row; ++j) {        for (int k = 0; k < s[3].column; ++k) {            printf("%f ",Wfp[k + j*s[3].column]);        }    printf("\n");    }    return true;}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 心脏支架又堵了怎么办 车辆验车过期了怎么办 车辆年审过期2天怎么办 违停单子丢了怎么办 沙发弹簧包坏了怎么办 bt种子被和谐了怎么办 苹果手机id密码忘了怎么办 墙漆颜色太深了怎么办 油漆颜色太深了怎么办 墙面漆颜色太深怎么办 古代打仗牙掉了怎么办 乐视电视没声音怎么办 老公疑心病很重怎么办啊 被安装了尿道锁怎么办 狼青小狗腿罗圈怎么办 备孕期间有霉菌怎么办 虫子进皮肤里了怎么办 生完孩子肚子越来越大怎么办 怀孕8个月肚子小怎么办 孕晚期胎儿不长怎么办 肚子上肉特别多怎么办 奶堵了有硬块怎么办 便秘5天肚子胀怎么办 上火大便拉不出来怎么办 大便拉不出来肚子痛怎么办 戒奶奶涨有硬块怎么办 忌奶的时候涨奶怎么办 娃儿隔奶,,奶涨怎么办 狗肚子很大很鼓怎么办 注册不了的二建怎么办 专升本没考过怎么办 警察乱拘留人该怎么办 玩英雄联盟太卡怎么办 一方离婚证丢了怎么办 遭遇呼死你软件怎么办 开车遇见碰瓷的怎么办 遇到碰瓷老人的怎么办 睿强遥控锁坏了怎么办 地暖分水器坏了怎么办 京东赠品无货怎么办 图书馆的书丢了怎么办