2010-10-02 88 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