如何fwrite和fread endianness独立整数,这样我就可以在许多机器上进行fwrite和fread,并且总是有相同的结果

时间:2016-10-22 14:31:12

标签: c fwrite endianness fread

fwrite一个整数取决于字节顺序,但有没有办法将一个整数0x00000004写入一个文件,这样它就可以始终作为0x00000004而不管它运行的机器。

  • 一种想法是写第一位,然后是第二位,然后第三位总是以特定顺序写入,例如使用模数或位移来抓取每个十进制值。

  • 不确定是否有办法强制fwrite以小端编写,而不进行一些复杂的检查以查看当前系统是否为大端,然后在写入之前反转这些位。

  • 另一个想法是将它作为ascii存储在文件中,这不是一个大问题,它只是将4个字节转换为8(十六进制)。但我认为这只是一个懒惰的解决方案。

我想从可能不同的机器进行fwrite和fread,所以这两个操作都需要能够伪装和伪装相同的endianness,而且我不确定(在搜索这个站点之后)以便携式方式执行此操作(没有使用某些模糊的库,可能在某些机器上,也可能不在某些机器上。)

2 个答案:

答案 0 :(得分:1)

我认为你不必担心比特级别的字节序,我认为它们总是一样的 how is data stored at bit level according to "Endianness"?

我可能会使用固定的endiannes来存储数据,并为fread和fwrite创建一些包装函数。

所以说你决定将所有内容存储在little endian中,包装器将检查机器的字节顺序并且:

  • 如果机器是小端,请直接使用fread和fwrite。
  • 如果机器是大端,则相应地交换字节。显然,你会假设只有int对齐的读/写(如果混合使用不同的长度类型,你的包装器将无法知道要交换的字节)。

编辑例如,你的fwrite可能看起来像这样(虽然没有经过测试,只是为了说明这个想法)。来自C program to check little vs. big endian的字节顺序检查:

size_t lendian_fwrite(const void *ptr, size_t size, size_t nmemb,
                     FILE *stream)
{
    if (size != 4)
    {
        /* Warn and exit */
    }

    int x = 1;

    if ( *((char*)&x) == 1)
    {
        /* Little endian machine, use fwrite directly */
        return fwrite(ptr, size, nmemb, stream);
    }
    else
    {
        /* Big endian machine, pre-process first */

        unsigned char *buffer = (unsigned char*) ptr;

        for (int i=0; i<nmemb; i++)
        {           
            unsigned char a = buffer[4*i];
            unsigned char b = buffer[4*i + 1];

            buffer[4*i] = buffer[4*i + 3];
            buffer[4*i + 1] = buffer[4*i + 2];
            buffer[4*i + 2] = b;
            buffer[4*i + 3] = a;
        }

        return fwrite(ptr, size, nmemb, stream);
    }  
}

答案 1 :(得分:0)

小即兴

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
static size_t lendian_fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream)
{
    int x = 1;

    if ( *((char*)&x) == 1)
    {
        /* Little endian machine, use fwrite directly */
        return fwrite(ptr, size, nmemb, stream);
    }
    else
    {
        if(size == sizeof(uint8_t))     //1 Byte
        {
            return fwrite(ptr, size, nmemb, stream);
        }
        else if(size == sizeof(uint16_t))   //2 Byte
        {
            /* Big endian machine, pre-process first */
            unsigned char *buffer = malloc(size*nmemb);
            unsigned char *input = (unsigned char*) ptr;

            for (uint32_t i=0; i<nmemb; i++)
            {           
                buffer[2*i] = input[2*i + 1];
                buffer[2*i + 1] = input[2*i];
            }
            int ret =fwrite((void*)buffer, size, nmemb, stream);      
            free(buffer);
            return ret;
        }
        else if(size == sizeof(uint32_t)) //4 Byte
        { 
            /* Big endian machine, pre-process first */
            unsigned char *buffer = malloc(size*nmemb);
            unsigned char *input = (unsigned char*) ptr;

            for (uint32_t i=0; i<nmemb; i++)
            {           
                buffer[4*i    ] = input[4*i + 3];
                buffer[4*i + 1] = input[4*i + 2];
                buffer[4*i + 2] = input[4*i + 1];
                buffer[4*i + 3] = input[4*i    ];
            }

            int ret =fwrite((void*)buffer, size, nmemb, stream);      
            free(buffer);
            return ret;
        }
        else if(size == sizeof(uint64_t)) //8 Byte
        { 
            /* Big endian machine, pre-process first */
            unsigned char *buffer = malloc(size*nmemb);
            unsigned char *input = (unsigned char*) ptr;

            for (uint32_t i=0; i<nmemb; i++)
            {           
                buffer[8*i    ] = input[4*i + 7];
                buffer[8*i + 1] = input[4*i + 6];
                buffer[8*i + 2] = input[4*i + 5];
                buffer[8*i + 3] = input[4*i + 4];
                buffer[8*i + 4] = input[4*i + 3];
                buffer[8*i + 5] = input[4*i + 2];
                buffer[8*i + 6] = input[4*i + 1];
                buffer[8*i + 7] = input[4*i    ];
            }

            int ret =fwrite((void*)buffer, size, nmemb, stream);      
            free(buffer);
            return ret;
        }
        else
        {
            printf("%s Function received invalid element size:%ld\n",__FUNCTION__,size);
            return -1;
        }
 
    }  
}


int main()
{
    
    uint8_t  buf1[8] = { 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88 };
    uint16_t buf2[4] = { 0x1122,0x3344,0x5566,0x7788 };
    uint32_t buf3[2] = { 0x11223344, 0x55667788 };
    uint64_t buf4 = { 0x1122334455667788 };

    FILE *ofp = NULL;
    
    if((ofp=fopen("file.bin","wb"))==NULL)
    {
        printf("Cannot open output file!");
        return -1;
    }

    lendian_fwrite(&buf1, sizeof(uint8_t),sizeof(buf1),ofp);
    lendian_fwrite(&buf2, sizeof(uint16_t),sizeof(buf2)/sizeof(uint16_t),ofp);
    lendian_fwrite(&buf3, sizeof(uint32_t),sizeof(buf3)/sizeof(uint32_t),ofp);
    lendian_fwrite(&buf4, sizeof(uint64_t),sizeof(buf4)/sizeof(uint64_t),ofp);

    fclose(ofp);

}