2

我有一个将一些数据写入文本文件的 C 函数。数据由浮点数、整数和字符串组成。它看起来像这样:

writeAsTextFile(  mystruct_t* myStructWithIntsFloatsAndStrings , const char* fileName);

为此,我使用对 fprintf 的调用;

现在我想写相同的数据,但作为二进制。我可以编写第二个函数 writeAsBinaryFile 并使用对 fwrite 的调用。但是每次我要更改 mystruct_t 的设计时,我都必须同时修改 writeAsTextFile 和 writeAsBinaryFile。当然还有对应的readAsTextFile和readAsBinaryFile。最重要的是,这将增加代码大小。因此,我想要一个带有一个 bin-or-text 参数的通用函数,如下所示:

writeToFile( mystruct_t* myStructWithIntsFloatsAndStrings , const char* fileName, myEnumType_t eOption)

例如,其中选项是枚举 eBin = 0 和 eTxt =1。根据 eOption,该函数将写入二进制或文本数据。

我不确定实现这一目标的最佳方法是什么。我是否也应该使用 fwrite 来写入文本,我应该尝试使用宏吗?(我在某处看到过使用 ## 指令但从未使用过它),或者我需要写入文件的任何地方的 switch/ifs 语句?或者我应该写一个通用函数,比如 myWriteFunction( void *data, char const type, myEnumType_t eOption)

writeToFile 会调用它吗?

我对使用 fread/fwrite 和宏不是很熟悉,所以欢迎任何最佳实践评论、想法等,

谢谢

爸爸

4

3 回答 3

1

对于您的情况,只需制作一个包装函数:

writeToFile(...,bool isBinary) {
  if (isBinary) {
    // write as binary file
  } else {
    // write as text file
  }
}

就 MACROS 而言,它们仅在您希望所有操作都是二进制或文本时才有用:

#ifdef __BINARY
#define WriteToFile(a,b,c,d,e) WriteToBinary(a,b,c,d,e)
#else
#define WriteToFile(a,b,c,d,e) WriteToText(a,b,c,d,e)
#endif

这在 winAPI 中用于在 ascii 函数和宽字符函数之间切换。

顺便说一句:如果您的结构包含 char* 或 std::string,则不会复制字符串内容,只会复制它的地址。这也适用于任何其他指针,例如 int* 或 std::vector。

于 2010-10-02T01:31:57.977 回答
1

您可以创建几个函数来在您的 中写入各种类型的数据struct

writeInt(File *f, myEnumType_t eOption, int data);
writeFloat(File *f, myEnumType_t eOption, float data);
writeFloatArray(File *f, myEnumType_t eOption, float *data, size_t n_data);

..然后二进制或文本测试隐藏在每个测试中。您的主要结构编写函数看起来像(省略了错误检查):

writeToFile(mystruct_t *myStruct, const char *fileName, myEnumType_t eOption)
{
    const char *fmode = eOption == EOPT_BIN ? "wb" : "w";
    FILE *f = fopen(filename, fmode);

    writeInt(f, eOption, myStruct->a);
    writeInt(f, eOption, myStruct->b);
    writeFloatArray(f, eOption, myStruct->values, myStruct->n_values);
    /* ... */
 }

所以对结构布局的改变只需要改变一个地方。

您还可以为不同的应用程序级“类型”实现不同的编写函数——例如,writeTemperature()可能与通用的writeFloat().

于 2010-10-02T07:37:09.473 回答
0

第一,不要把功能组合起来,没有实际的节省。

其次,每次使用该结构时都必须编写一个新的 write as text 函数,这是没有办法的(除了一些非标准的序列化库)。

第三,只要不改变结构成员的顺序,只在结构的末尾添加新成员,就永远不需要编写新的二进制写入器或读取器。为了做到这一点,您应该将结构的大小写入文件,然后将结构写入文件。

这样,您的读取函数将读取结构的大小(写入时)并知道要读取多少字节。如果您的结构发生更改,您的程序将能够从旧结构版本中读取部分,并且结构末尾的新成员将被取消初始化。

编辑

用指针编写结构将写入指针的值。读取结构时必须非常小心,因为指针将指向基本上随机的内存和平。b

如果要维护结构之间的关系,则必须提出自己的机制。这在难度上有所不同,您必须提出一些预定义的顺序来写入结构,并在读取结构时重建所有指针。

于 2010-10-02T01:32:36.033 回答