2016-03-05 158 views
0

我正在寫一個函數,該函數應該在二進制文件中保存3個結構(其中2個是結構數組)。這裏是我的功能:將多個結構保存爲二進制文件(C)

void saveFile(Struct1 *s1, Struct2 *s2, Struct3 s3) { 
    FILE *fp = NULL; 
    fp = fopen("save.bin", "w+b"); 

    if (fp == NULL) { 
     printf("Save failed.\n"); 
    } 

    fwrite(s1, sizeof(Struct1), struct3.nElements, fp); 
    fwrite(s2, sizeof(Struct2), NELEMENTS, fp); 
    fwrite(&s3, sizeof(Struct3), 1, fp); 

    printf("Save done.\n"); 
} 

s1struct3.nElementss2NELEMENTS(這是一個常數)和s3只是一個結構,而不是一個數組。當我嘗試使用HexEditor打開save.bin時,它給出了與我期望的結果截然不同的結果,我想知道是否正確使用了fwrite函數,特別是對於結構數組。

+1

你使用十六進制編輯器得到了哪個結果,你期望得到哪個結果,以及你寫入了什麼文件。如果你想得到答案,你必須與我們分享這些信息。閱讀[MCVE](http://stackoverflow.com/help/mcve)。 –

+0

@MichaelWalz當我使用HexEditor時,我看到了隨機字符,一些正確的'struct2'字段以及一些像Visual Studio程序的路徑。顯然,我期待看到結構的正確價值。 – THZ

+1

顯示如何調用'saveFile'。問題可能在那裏。並顯示'struct1','struct2'和'struct3'的聲明。 –

回答

1

有小的問題跟你的功能可能會引發問題:

  • 您定義的函數,通過數值取s3。爲什麼不把指針傳遞給第三個struct?調用代碼之前saveFile函數是否正確聲明?你確定調用代碼的價值通過struct

  • 忘記關閉流。手柄會丟失,並且內容不會刷新到磁盤,直到程序退出。

  • 您在"w+b"模式下打開文件:使用read進行寫入。使用二進制模式是正確的,但不必爲了讀取而添加+。只需使用"wb"

  • 如果fopen失敗,則輸出診斷消息,但不會從該函數返回。嘗試寫入NULL流指針時,您將調用未定義的行爲。

關於你的問題,文件的轉儲與你期望的不一致......給我們更多的信息,比如不同結構和十六進制轉儲的定義。這裏有一些想法:

  • 結構中的某些字段可能需要特定的對齊,並因此通過填充字節與前一字段分離。這些填充字節的值不一定是0:如果結構處於自動存儲或分配給malloc,則它們的初始狀態未定義,並且可能會改變爲存儲其他字段的副作用。
  • 整數可以具有不同的大小,並且可以按文件中的小端或大端順序存儲,具體取決於程序編譯的特定體系結構。由於這個原因,程序存儲的值只能在相同的體系結構和操作系統上運行,並使用合適的但相當類似的代碼讀回。
  • 如果您的結構包含指針,您無法從存儲在輸出文件中的值中真正理解。
+0

「忘記關閉流,句柄丟失,內容不會刷新到磁盤,直到程序退出。」是最好的嫌疑犯。 AFAIK,如果缺少close/flush,數據甚至不需要寫入。 – chux

+0

@chux:C11 7.22.4.4:'exit'函數:*接下來,所有打開的未經寫入的緩衝數據流將被刷新,所有打開的流將關閉,並刪除由tmpfile函數創建的所有文件* – chqrlie

+1

True,但代碼不會公佈如何結束。考慮'中止_Exit'。 「打開的流被關閉,或臨時文件被移除是實現定義的」OP的反射來發布完整的MCVE結構,數據讀取和觀察到的數據都會在回答這篇文章時造成不必要的挑戰。 – chux