2010-10-02 116 views
2

我有一个C函数,它将一些数据写入文本文件。数据由浮点数,整数和字符串组成。 它看起来是这样的:将文本或二进制数据写入单个C函数

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

这样做我用调用fprintf中;

现在我想写的相同的数据,但二进制。我可以编写第二个函数writeAsBinaryFile,并使用调用fwrite来代替。但是,每次我将改变mystruct_t的设计,我将不得不修改writeAsTextFile和writeAsBinaryFile。当然还有相应的readAsTextFile和readAsBinaryFile。最重要的是这将增加代码量。 因此,我想有一个箱子,或文本参数一个单一的通用函数,应该是这样的:

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

其中选择将是一个枚举EBIN = 0和eTxt = 1的实例。根据eOption,该函数将写入二进制或文本数据。

我不知道什么是最好的方式来实现这一点。我是否也应该使用fwrite写作文本,我应该尝试使用宏吗? (我已经看到使用##指令的地方,但从来没有使用它),或切换/ ifs声明无论我需要写入文件?或者我应该写一个通用函数,如 myWriteFunction(void *data, char const type, myEnumType_t eOption)

这将被writeToFile调用吗?

我不是很熟悉使用FREAD/FWRITE和宏,以便任何的最佳做法的意见,想法等是值得欢迎的,

感谢

巴巴

+0

当您处于设计数据文件的模式时,您是否考虑过像JSON或XML这样更通用的东西?然后所有写入都是文本写入。您几乎可以在任何其他编程环境中阅读您的文件,并且不会比现在正在做的更多工作。站在走在你面前的巨人的肩膀上。 – dawg 2010-10-02 02:53:03

回答

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()不同。

1

对于你的情况,简单地做一个包装功能部件:

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

至于宏去,如果你希望所有的操作是二进制或文本,他们是唯一有用的:

#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。

0

首先,不结合功能,实际上没有节省。

其次,每当你使用该结构时,你将不得不作为文本函数写一个新的写入,除了一些非标准的序列化库外,没有办法解决这个问题。第三,只要你永远不改变结构成员的顺序,并且只在结构的末尾添加新成员,你将永远不需要编写新的二进制编写器或读取器。为了做到这一点,你应该把结构的大小写入文件,然后把结构写入文件。

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

EDIT

写入具有指针的结构体将写入指针的值。读取结构时必须非常小心,因为指针会指向基本上随机的内存平衡。如果要维护结构之间的关系,则必须提供自己的机制。这个难度会有所不同,您必须拿出一些预定义的顺序来写入结构,并在读取结构时重建所有的指针。

+0

谢谢。我应该提到我的结构包含指向浮点数组的指针,以及包含浮点数,整型等的各种其他结构。我可以跟踪mystruct的总大小,但即使如此,当我调用fwrite写入整个结构时,我猜测是只有指向我分配的数组的指针才会被复制,而不是数组的内容。我对吗? – Baba 2010-10-02 01:49:39

+0

@Baba,更新了我对此的回应。 – mikerobi 2010-10-02 02:41:00