问一个 C 语言关于文件操作的问题,如何将 uint32_t 数据写进二进制文件, 4byte 对齐? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
ReputationZh
V2EX    Linux

问一个 C 语言关于文件操作的问题,如何将 uint32_t 数据写进二进制文件, 4byte 对齐?

  •  
  •   ReputationZh 2020-08-24 23:59:21 +08:00 3185 次点击
    这是一个创建于 1874 天前的主题,其中的信息可能已经有所发展或是发生改变。
    fwrite 的第一个参数是 char 类型,好像不支持啊?应该用什么方法写入。
    21 条回复    2020-08-27 09:28:45 +08:00
    dangyuluo
        1
    dangyuluo  
       2020-08-25 00:01:56 +08:00
    在不考虑字节序的情况下,盲猜每次读 8bit 再写入?
    louettagfh
        2
    louettagfh  
       2020-08-25 00:12:15 +08:00
    1. open 的时候加参数 binary
    2. 写对齐没有意义
    zwy100e72
        3
    zwy100e72  
       2020-08-25 00:27:20 +08:00   1
    第一个不是 char 类型,而是指向 buffer 的一个指针;第二个参数是 buffer 的长度,因此要达到写 4 bytes (sizeof(uint32_t))的效果,你需要 ( https://godbolt.org/z/zMMWb3 ):

    ```c
    #include <cstdint>
    #include <cstdio>

    void f(uint32_t i) {
    FILE* fp = fopen("path/to/file.bin", "wb");
    fwrite(&i, sizeof(i), 1, fp);
    fclose(fp);
    }
    ```

    https://en.cppreference.com/w/c/io/fwrite
    XiaoxiaoPu
        4
    XiaoxiaoPu  
       2020-08-25 00:27:54 +08:00
    需要先把 uint32_t 转化成 4 个 char,这里涉及大小端的问题,可以搜一下「大小端」
    zwy100e72
        5
    zwy100e72  
       2020-08-25 00:29:14 +08:00
    对齐与否之前只有在内存中才有必要对齐,更何况现在不对齐的内存访问也已经很快了,你没有必要对齐
    baoshuo
        6
    baoshuo  
       2020-08-25 01:00:02 +08:00
    对齐感觉没用
    Tony042
        7
    Tony042  
       2020-08-25 02:12:13 +08:00
    不知道 C 怎么做,C++内置了关键字 直接 alignas(4) uint_32 即可
    laminux29
        8
    laminux29  
       2020-08-25 03:29:20 +08:00
    C 语言层次,我不建议你去主动对齐,因为这个层次的文件读写,本质是把 buffer 交给 OS 去处理的,最后这些 buffer data 写到存储设备时,是否进行对齐 io,是由 OS 来决定的。

    OS 在把数据 flush 到存储设备上的优化动作,可不止对齐一种。
    yngzij
        9
    yngzij  
       2020-08-25 07:46:39 +08:00 via iPhone
    我记得只有在 malloc 的时候对齐吧
    chinuno
        10
    chinuno  
       2020-08-25 08:37:12 +08:00 via Android
    (char*)&num 直接转成 char 类型数组写入 4 个字节就行。本身 uint32_t 就是 4 个字节也不用考虑对齐问题吧。读的时候四个四个读把 char 数组转回 uint32_t 也不用考虑字节序的问题了
    shuax
        11
    shuax  
       2020-08-25 08:52:29 +08:00
    uint32_t 不就是 4 个字节,还对齐什么
    heguangyu5
        12
    heguangyu5  
       2020-08-25 09:32:36 +08:00
    mmap 要写入的文件,然后 align 要写入的地址,然后 memcpy.

    类似这样:

    fd = open()
    addr = mmap()
    ptr = addr + offset
    ptr = align()
    memcpy(ptr, &int_var, sizeof(int))
    yolee599
        13
    yolee599  
       2020-08-25 09:33:13 +08:00
    要考虑大端还是小端储存
    May725
        14
    May725  
       2020-08-25 12:14:42 +08:00 via iPhone
    以 binary 形式打开文件,写多少个字节就是多少个字节
    Chenamy2017
        15
    Chenamy2017  
       2020-08-25 12:55:45 +08:00
    看#3,怎么写进去将来用的时候怎么读出来就行了。
    CRVV
        16
    CRVV  
       2020-08-25 13:04:14 +08:00
    size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

    fwrite 的第一个参数明明是 const void* 类型

    直接
    uint32_t x;
    fwrite(&x, 4, ...)
    应该就能用

    另外,没有理解楼主说的 对齐 是指什么,如果从头开始写,每次写 4 bytes,那当然是对齐到 4 bytes 上的
    wizardoz
        17
    wizardoz  
       2020-08-25 13:13:34 +08:00
    我感觉直接写就是对齐的,为此我还特意写代码测试了一下:
    #include <stdio.h>

    typedef struct {
    char a;
    int b;
    char c;
    } Test_t;

    int main(int argc, char* argv[]) {
    Test_t test = {
    .a = 1,
    .b = 2,
    .c = 3
    };

    FILE *fp = fopen("/tmp/data.bin", "wb");
    if (fp != NULL) {
    fwrite(&test, sizeof(test), 1, fp);

    fclose(fp);
    }
    return 0;
    }

    文件内容:
    00000000: 0156 0000 0200 0000 037f 0000 0a .V...........
    wizardoz
        18
    wizardoz  
       2020-08-25 13:16:31 +08:00
    你写到文件是几字节对齐应该是与你的数据在内存中是几字节对齐一致的,毕竟写的时候只是把内存原样写进去。
    如果你设置了内存 1 字节对齐,那么写到文件也是 1 字节对齐的。
    CRVV
        19
    CRVV  
       2020-08-25 13:21:18 +08:00
    @wizardoz

    struct 里面的 field 都会 self-align,把 int b 放到 char a 前面,char c 就不会 align 到 4 bytes 上了。
    ReputationZh
        20
    ReputationZh  
    OP
       2020-08-27 09:26:04 +08:00
    @zwy100e72 感谢大佬,不过我有个疑问,假设我的数据类型是 uint32_t,但是我 fwrite 的时候大小填写的 5 或者 8 (不为 uint32_t 的 4 ),我写进去的数据是真实的吗?多余的字节数会产生什么异变吗?
    ReputationZh
        21
    ReputationZh  
    OP
       2020-08-27 09:28:45 +08:00
    @wizardoz 理解了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2750 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 09:12 PVG 17:12 LAX 02:12 JFK 05:12
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86