2012-05-28 136 views

回答

7

這取決於你在做什麼。爲了順序讀寫文本文件,iostream絕對是最佳選擇。對於涉及交易安全或非標準設備的任何事情,您必須直接訪問系統(CreateFileopen)。即使如此,對於連續閱讀和編寫文本,最好的解決方案是定義您自己的streambuf,並將其用於iostream。我想不出fopen會更好。

+0

我想要力量:)寫和讀二進制。僅用於windows系統。我聽說open和fopen與createfile不匹配?這是真的嗎? – Eveler

+1

@Eveler:如果你想要全功能,那麼你可以做的最快的事情就是用'CreateFile'打開它,並用'CreateFileMapping'將它映射到內存中,如[本博文]中所示(http: //blogs.msdn.com/b/oldnewthing/archive/2005/05/13/417183.aspx),它是從[標準C++](http://blogs.msdn.com/)開始的優化系列的一部分。 b/oldnewthing/archive/2005/05/10/415991.aspx),然後逐步移至[Win32優化代碼](http://blogs.msdn.com/b/oldnewthing/archive/2005/05/19/420038的.aspx)。但在大多數情況下,簡單的標準C和C++都可以。 – 2012-05-28 09:46:40

+3

'fopen'是一個更高層次的函數,在C++中被'fstream :: open'取代。 'CreateFile'和'open'是系統級功能,在Windows中是第一個,在Unix中是第二個。他們不提供完全相同的東西,因爲系統支持不同的功能。 –

1

在大多數情況下,你會更好地在C或C++中使用fopen。 CreateFile對共享和緩存提供了一些額外的控制,但不提供格式化功能。

+1

所以你寫了一個'streambuf',它使用'CreateFile'來滿足你的需要,並且獲得了兩者的優點。 –

+0

我一直在想,爲什麼插入一個新的源或目的地到IOstream非常麻煩。如果有的話,C++可以很容易地爲數據寫入器/讀取器聲明純粹的抽象類... – 2015-12-22 17:52:06

4

除非你需要通過Windows文件函數提供的功能(例如,重疊I/O),那麼我的建議是在C兩種輸入輸出流++或FILEfopen和朋友)在C.

去除了是更便攜,你也可以爲文本文件使用格式化的輸入/輸出,而對於C++來說,很容易使你的類的輸出/輸入操作符過載。

+2

從std :: streambuf和一些「特殊」功能(事務完整性,特殊設備等)。 –

2

除非您絕對需要OS API函數提供的額外功能(如CreateFile),否則我會推薦使用標準庫函數(如fopenofstream)。這樣你的程序將更加便攜。

我能想到的使用CreateFile的唯一真正優點是重疊的I/O和更細粒度的訪問權限。

+2

Createfile可以打開超過260個字符長度的文件路徑。 – Eveler

+0

夠公平! +1 – cyco130

2

如果你想使用Windows文件內存映射你應該使用CreateFile(例如傳遞給CreateFileMapping API的HANDLECreateFile的返回值)。此外,CreateFile提供比C和C++標準文件API更高的定製選項。但是,如果要編寫便攜式代碼,或者如果不需要特定於Windows的功能,則C和C++標準文件API就足夠了。 在一些測試中,當處理大數據時,我注意到C++ I/O流與原始C文件API相比的一些性能開銷;如果碰巧遇到這種情況,可以簡單地將原始C文件API包裝在某些C++ RAII類中,並仍然在C++代碼中使用它。

+0

我需要從4GB到10GB +的大數據文件,我也會使用mem映射。 – Eveler

+0

因此,如果您需要內存映射,則可以使用直接的Win32 API調用並將它們包裝在C++ RAII類中。 – 2012-05-28 10:49:12

0

我複製我的回答從

fopen or CreateFile in Windows

其關閉出於某種原因其脫離了我......

  1. 沒有爲fopen()函數返回系統錯誤沒有定義的方式碼。可能存在未定義的訪問errno的方式,但這可能與系統錯誤代碼相同或可能不同。我不認爲有一個定義的方式來訪問真正的系統句柄(類型HANDLE),反過來,你可能想用它來傳遞給許多win64系統調用之一,期望這樣的系統句柄(例如內存映射IO)
  2. 使用open()一個整數表示文件句柄,它不是系統句柄(在窗口上)。
  3. fopen()在發生錯誤時不會拋出異常。爲了擁有一些RAII,你需要將它包裝到一個類中。
  4. 將CreateFile()包裝到類中並不比將fopen()或open()包裝到類中更昂貴。
  5. 使用C++的功能(的std :: ofstream的,性病:: ifstream的)寫/讀/來自文件從同一問題的困擾如fopen()函數:
    • 它不會在默認情況下錯誤拋出。爲了啓用此功能,您需要調用某些方法,而不是使用某些構造函數參數 - 對於RAII,您需要派生此類(以便將其用作拋出錯誤的成員/基類) 。
    • 如果能夠從引發的異常中檢索系統錯誤代碼,或者從what()告訴你有關係統錯誤的任何信息,那麼它是未定義的。
    • 使用此流接口沒有真正的可插入接口來定義讀取或寫入的源或目標。重載流接口非常麻煩並且容易出錯。
  6. 用C編程一樣(注意或忽略返回代碼和手動編寫清理代碼)是許多罪惡的根源(記得心臟,流血?)...

結論:

  1. 爲CreateFile()/ CloseHandle()編寫資源包裝器。資源包裝器是一個類,它在構造函數中執行do-action,在析構函數中執行undo-action,並在出錯時拋出異常。在每個操作系統中都有很多這樣的系統調用,特別是在Win64中。
  2. 編寫一個系統錯誤異常類(在CreateFile()失敗的情況下用於上面的類以及所有其他系統錯誤)或調查新的system_exception類(在C++ 0x中)實際上在做什麼如果它足夠。
  3. 寫的ReadFile()和WriteFile(),它的系統誤差轉換成拋出系統異常對象的功能包裝...
  4. 潛在定義自己的接口的地方寫入和讀出的地方,這樣就可以實現其他東西獨立於從源/目的地的類型讀取/寫入。
  5. 編寫一個緩存類,允許您緩存讀取或寫入到某處,也是兒童遊戲。當然,緩存類不應該知道也不關心你寫入/讀取的源/目的地。

不要害怕這些小任務。實際上,您會知道,代碼中發生了什麼,與調用它的代碼相比,這些小代碼應該可以忽略不計(代碼行數量)。同樣,如果您使用RAII處理所有事情,調用這些實用程序類的代碼相比不使用RAII並且不得不使用兩步甚至更多步初始化並且相對較少出錯的代碼要少得多。用其他操作系統的等價實用程序類替換這些實用程序類也是子操作(在UNIX上使用open()/ close()/ read()/ write())。

而爲了千百年來的不讀谷歌編程指導方針!