加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

C语言fread/fwrite填坑记

发布时间:2020-12-14 02:04:19 所属栏目:Linux 来源:网络整理
导读:先说结论 用 fread 或 fwrite 的时候,如果是要写入 字符 ,那么打开的文件、读取的文件,用 字符模式( w 和 r ) FILE* fin = fopen("filename","w");fread(buf,sizeof(char)*num_elem,1,fin);fclose(fin); FILE *fout = fopen("filename","r");fwrite(buf

先说结论

freadfwrite的时候,如果是要写入字符,那么打开的文件、读取的文件,用字符模式(wr

FILE* fin = fopen("filename","w");
fread(buf,sizeof(char)*num_elem,1,fin);
fclose(fin);
FILE *fout = fopen("filename","r");
fwrite(buf,fout);
fclose(fout);

如果是要写入非字符的数据,例如float数组、int数组等,则一定要用二进制模式打开文件(wbrb)(尽管在linux和mac下你的结果也许一直没问题,但是保不准到了windows下会出错):

FILE* fin = fopen("filename","wb");
fread(buf,sizeof(float)*num_elem,"rb");
fwrite(buf,fout);
fclose(fout);

原因:字符模式打开的文件,在windows下,遇到0x0D和0x0A(分别是rn)会替换为0x0A进行写入(也就是n)。

举例细说

读取图像,通常用opencv,但是考虑到arm上用opencv过于庞大,考虑在pc上把图像的数据读取出来,然后整理下顺序,再用fwrite保存。后面在arm上直接fread就行了,避开了opencv。

但在具体实现的时候发现,fwrite后再fread,只有前面一部分数据是正确的!原因如上面说的,保存到文件的是float数组,但是打开文件的模式错误的设定为了字符模式,而不是二进制模式。

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

#include <iostream>
#include <string>

#include <vector>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main() {
    string im_pth = "../cat_227.jpg";
    IplImage* img = cvLoadImage(im_pth.c_str(),CV_LOAD_IMAGE_COLOR);

    int iImgChnl = 3;
    int iImgHgt = 227;
    int iImgWth = 227;
    int num_elem = iImgChnl * iImgHgt * iImgWth;
    float* pfImgData;
    pfImgData = (float*)malloc(sizeof(float)*num_elem);

    float* f_input_data_b = (float*)malloc(sizeof(float)*iImgHgt*iImgWth);
    float* f_input_data_g = (float*)malloc(sizeof(float)*iImgHgt*iImgWth);
    float* f_input_data_r = (float*)malloc(sizeof(float)*iImgHgt*iImgWth);

    for (int i = 0; i < num_elem; i += 3) {
        f_input_data_b[i / 3] = (float)(unsigned char)(img->imageData[i]);
        f_input_data_g[i / 3] = (float)(unsigned char)(img->imageData[i + 1]);
        f_input_data_r[i / 3] = (float)(unsigned char)(img->imageData[i + 2]);
    }

    for (int i = 0; i < iImgHgt*iImgWth; i++) {
        pfImgData[i] = f_input_data_b[i];
    }
    for (int i = 0; i < iImgHgt*iImgWth; i++) {
        pfImgData[i + iImgHgt*iImgWth] = f_input_data_g[i];
    }
    for (int i = 0; i < iImgHgt*iImgWth; i++) {
        pfImgData[i + 2*iImgHgt*iImgWth] = f_input_data_r[i];
    }
    int ret;

    string save_pth = "../cat_227.fread_float.w";
    FILE* fout = fopen(save_pth.c_str(),"w");
    ret = fwrite((void*)pfImgData,sizeof(float),num_elem,fout);
    fclose(fout);

    printf("--- pfImgData[5847]=%f,pfImgData[5848]=%fn",pfImgData[5847],pfImgData[5848]);

    //--------------------------------------------------
    float* tuopan = (float*)malloc(sizeof(float)*num_elem);
    FILE* fin = fopen(save_pth.c_str(),"rb");
    ret = fread((void*)tuopan,fin);
    fclose(fin);

    printf("--- tuopan[5847]=%f,tuopan[5848]=%fn",tuopan[5847],tuopan[5848]);

    printf("--- check here---n");

    return 0;
}

测试环境:VS2013 update5,win32/x64 debug/release模式

调试结果:

发现第5848个元素是错误的。

通过分别设定字符模式和二进制模式来写入文件,看到了差异:

第一次出现差异的地方是0x5B60后的一个元素,0x5B60恰好是十进制下的23392,23392=5848 x 4,4表示sizeof(float)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读