如何将结构数组的二进制副本写入文件

时间:2014-08-21 03:31:34

标签: c arrays file pointers struct

我想将结构数组的二进制图像写入二进制文件。到目前为止我试过这个:

#include <stdio.h>
#include <string.h>
#define NUM 256

const char *fname="binary.bin";


typedef struct foo_s {
    int intA;
    int intB;
    char string[20];
}foo_t;



void main (void)
{
    foo_t bar[NUM];

    bar[0].intA = 10;
    bar[0].intB = 999;
    strcpy(bar[0].string,"Hello World!");

    Save(bar);
    printf("%s written succesfully!\n",fname);
}

int Save(foo_t* pData)
{
    FILE *pFile;
    int ptr = 0;
    int itr = 0;

    pFile = fopen(fname, "w");
    if (pFile == NULL) {
        printf("couldn't open %s\n", fname);
        return;
    }
    for (itr = 0; itr<NUM; itr++) {
        for (ptr=0; ptr<sizeof(foo_t); ptr++)
        {
            fputc((unsigned char)*((&pData[itr])+ptr), pFile);
        }
        fclose(pFile);
    }  
}

但是编译器说aggregate value used where an integer was expected fputc((unsigned char)*((&pData[itr])+ptr), pFile);并且我不太明白为什么,我做错了什么?

谢谢!

4 个答案:

答案 0 :(得分:2)

问题1

使用正确的模式打开文件。

pFile = fopen(fname, "wb");

问题2

fclose的来电是错误的。

for (itr = 0; itr<NUM; itr++) {
  for (ptr=0; ptr<sizeof(foo_t); ptr++)
  {
    fputc((unsigned char)*((&pData[itr])+ptr), pFile);
  }
  fclose(pFile);
}

您在写出第一个foo_t的数据后关闭了该文件。后续调用将导致未定义的行为,因为您将使用已关闭的fputc来调用FILE*

必须将对fclose的调用移出循环。

for (itr = 0; itr<NUM; itr++) {
  for (ptr=0; ptr<sizeof(foo_t); ptr++)
  {
    fputc((unsigned char)*((&pData[itr])+ptr), pFile);
  }
}
fclose(pFile);

问题3

您尝试访问循环中的字节的方式不正确。这是循环:

for (itr = 0; itr<NUM; itr++) {
  for (ptr=0; ptr<sizeof(foo_t); ptr++)
  {
    fputc((unsigned char)*((&pData[itr])+ptr), pFile);
  }
}

以下是您尝试获取字节的行。

    fputc((unsigned char)*((&pData[itr])+ptr), pFile);
                           ^           ^
                           This is of type `foo_t*`

    fputc((unsigned char)*((&pData[itr])+ptr), pFile);
                          ^                 ^
                          This pointer arithmetic is done on `foo_t*`.
                          It is not pointer arithmetic done on `char*`.
                          You are going to run into out of bound memory access
                          very quickly.

    fputc((unsigned char)*((&pData[itr])+ptr), pFile);
                         ^                  ^
                         This is dereferencing a `foo_t*`, which
                         means it is of type `foo_t`.

由于您尝试将foo_t转换为unsigned char,因此收到编译错误。

要保存foo_t,您可以采取两种方法。您可以使用fwrite在一次通话中保存整个foo_t

for (itr = 0; itr<NUM; itr++) {
  fwrite(&(pData[itr]), sizeof(foo_t), 1, pFile);
}

如果你必须使用我认为不需要的fputc写每个字节,你将不得不稍微改变你的代码。

以下内容应该有效:

for (itr = 0; itr<NUM; itr++) {
  cp = (char*)&pData[itr];  // Declare char* cp in the function.
  for (ptr=0; ptr<sizeof(foo_t); ptr++)
  {
    fputc(cp[ptr], pFile);
  }
}

答案 1 :(得分:1)

要写入二进制文件,您需要以w + b模式打开文件。 然后使用fwrite写入文件。 它应该工作。

pFile = fopen(fname, "w+b");

而不是fputc使用fwrite。

fwrite ((foo_t *)&pData[itr], sizeof(foo_t), 1, pFile);

答案 2 :(得分:1)

  1. 确保以二进制模式打开文件。

    // pFile = fopen(fname, "w");
    pFile = fopen(fname, "wb");
    
  2. 在编制索引之前转换为char *指针。 sizeof(pData[itr])的原始代码索引。 [编辑]然后取消引用该类型 - 然后尝试强制转换为unsigned char @R Sahu

    //fputc((unsigned char)*((&pData[itr])+ptr), pFile);
    unsigned char *p = (unsigned char *) (&pData[itr]);
    fputc(p[ptr], pFile);
    
  3. 正如@R Sahu指出的那样:fclose()应该移到循环之外。

  4. 次要:

    1. 推荐传递NUM作为save()的参数。

    2. foo_t bar[NUM];尚未完全初始化。

    3. 非循环解决方案

      if (fwrite(pData, sizeof(*pData), NUM, pFile) == NUM) Success();
      
    4. 建议制作const:`int Save(const foo_t * pData)

    5. 最好将size_t用于ptr&amp; itr

答案 3 :(得分:0)

我认为你需要做的只是写它。

foo_t fooarry[SOME_SIZE];

fd = open(fname, O_WRONLY);
write(fd, fooarry, SOME_SIZE * sizeof(foo_t));

更新: 如果你想使用文件流,请按以下步骤操作:

fwrite(fooarry, siezeof(foo_t), SOME_SIZE, pFile);