fopen, _wfopen

開啟檔案。 這些函式的更安全版本,可執行更多參數驗證和傳回錯誤碼;請參閱 fopen_s_wfopen_s

語法

FILE *fopen(
   const char *filename,
   const char *mode
);
FILE *_wfopen(
   const wchar_t *filename,
   const wchar_t *mode
);

參數

filename
檔案名稱

mode
啟用的存取類型。

傳回值

每一個這些函式都會傳回已開啟的檔案的指標。 null 指標值表示錯誤。 如果 filenamemode 為 或 空 NULL 字串,這些函式會觸發不正確參數處理常式,如參數驗證 中所述 。 如果允許繼續執行,這些函式會傳回 NULL,並將 errno 設為 EINVAL

如需詳細資訊,請參閱errno, _doserrno, _sys_errlist_sys_nerr.

備註

fopen 式會開啟 所 filename 指定的檔案。 根據預設,窄 filename 字串會使用 ANSI 字碼頁 ( CP_ACP ) 來解譯。 在 Windows 傳統型應用程式中,可以使用 函式變更為 OEM 字碼頁 。 CP_OEMCPSetFileApisToOEM 。 您可以使用 函 AreFileApisANSI 式來判斷是 filename 使用 ANSI 或系統預設 OEM 字碼頁來解譯。 _wfopen 是 的寬字元版本 fopen ;自 _wfopen 變數為寬字元字串。 否則 _wfopenfopen 的行為相同。 只要使用 _wfopen 不會影響檔案資料流程中使用的自動程式碼字元集。

fopen 接受執行之時在檔案系統上為有效的路徑; fopen 接受 UNC 路徑以及包含對應的網路磁碟機的路徑,只要執行程式碼的系統在執行時有權存取共用或對應磁碟機即可。 當您建構 的路徑 fopen 時,請確定執行環境中有可用的磁片磁碟機、路徑或網路共用。 您可以使用正斜線 ( / ) 或反斜線 ( \ ) 作為路徑中的目錄分隔符號。

請務必檢查傳回值,以查看指標是否為 Null,再對檔案執行任何其他作業。 如果發生錯誤,則會設定全域變數 errno ,而且可用來取得特定錯誤資訊。 如需詳細資訊,請參閱errno, _doserrno, _sys_errlist_sys_nerr.

根據預設,此函式的全域狀態會限定于應用程式。 若要變更它,請參閱 CRT 中的全域狀態。

Unicode 支援

fopen 支援 Unicode 檔案資料流。 若要開啟 Unicode 檔案,請將指定所需編碼方式的 ccs=encoding 旗標傳遞給 fopen,如下所示。

FILE *fp = fopen("newfile.txt", "rt+, ccs=UTF-8");

編碼的 ccsUNICODE 允許值為 、 UTF-8UTF-16LE

使用 Unicode 模式開啟檔案時,請輸入函式,將從檔案讀取的資料,轉譯為儲存為類型 wchar_t的 UTF-16 資料。 寫入檔案的函式會以 Unicode 模式開啟,但包含儲存為類型 wchar_t之 UTF-16 資料的緩衝區除外。 如果檔案編碼為 UTF-8,則寫入 UTF-8 時,UTF-16 資料會轉譯為 UTF-8。 檔案的 UTF-8 編碼內容會在讀取時轉譯為 UTF-16。 嘗試以 Unicode 模式讀取或寫入奇數位元組會導致 參數驗證 錯誤。 若要讀取或寫入作為 UTF-8 儲存在您程式裡的資料時,請使用文字或二進位檔案模式,不要使用 Unicode 模式。 您必須負責任何必要的編碼轉譯。

如果檔案已經存在且已開啟以供讀取或附加,則檔案中的任何位元組順序標記 (BOM) 會決定編碼方式。 BOM 編碼的優先順序高於 旗標所 ccs 指定的編碼。 當 BOM 不存在或檔案為新檔案時,只能使用 ccs 編碼方式。

注意

BOM 偵測只適用於以 Unicode 模式 (也就是,透過傳遞 ccs 旗標) 開啟的檔案。

下表摘要說明可用於各種指定給 ccs 及檔案中位元順序標記之 fopen 旗標的模式。

以 ccs 旗標和 BOM 為基礎的編碼

ccs 旗標 沒有 BOM (或新檔案) BOM:UTF-8 BOM:UTF-16
UNICODE UTF-16LE UTF-8 UTF-16LE
UTF-8 UTF-8 UTF-8 UTF-16LE
UTF-16LE UTF-16LE UTF-8 UTF-16LE

開啟以供在 Unicode 模式下寫入的檔案會有 BOM 自動寫入其中。

如果 modea, ccs=encoding 某個 encoding 值, fopen 請先嘗試使用讀取和寫入存取來開啟檔案。 如果此動作成功,函式會讀取 BOM 以判斷檔案的編碼方式。 如果失敗,函式會使用檔案的預設編碼方式。 不論是哪一種情況, fopen 都使用唯寫存取權重新開啟檔案。 (此行為 "a" 僅適用于模式,不適用於 "a+" 模式。

泛型文字常式對應

TCHAR.H 常規 _UNICODE_MBCS 未定義 _MBCS 定義 _UNICODE 定義
_tfopen fopen fopen _wfopen

字元字串 mode 會指定對檔案要求的存取類型,如下所示。

mode 存取權限
"r" 開啟以讀取。 如果檔案不存在或找不到,呼叫 fopen 就會失敗。
"w" 開啟空白檔案以寫入。 如果指定的檔案已存在,其內容將被終結。
"a" 開啟以供在檔案結尾寫入 (附加),並且在將新資料寫入檔案之前,不會移除檔案結尾 (EOF) 標記。 如果該檔案不存在,則建立檔案。
"r+" 開啟以進行讀取和寫入。 檔案必須存在。
"w+" 開啟空白檔案以進行讀取和寫入。 如果檔案存在,其內容會遭到銷毀。
"a+" 開啟以進行讀取和附加。 附加作業包括在將新資料寫入檔案之前移除 EOF 標記。 寫入完成後,不會還原 EOF 標記。 如果該檔案不存在,則建立檔案。

使用 "a" 存取類型或 "a+" 存取類型開啟檔案時,所有寫入作業都會在檔案結尾進行。 檔案指標可以使用 fseekrewind重新調整位置,但是在執行任何寫入作業之前,一律會移回至檔案結尾。 因此,無法覆寫現有的資料。

模式 "a" 不會在附加至檔案之前移除 EOF 標記。 進行附加之後,MS-DOS TYPE 命令只顯示到原始 EOF 標記為止的資料,任何附加至檔案的資料都不會出現。 "a+" 模式會在附加到檔案之前移除 EOF 標記。 附加之後,MS-DOS TYPE 命令會顯示檔案中的所有資料。 附加 "a+" 至以 Z EOF 標記終止的 CTRL+ 資料流程檔案時,需要模式。

指定 "r+""w+""a+" 存取類型時,會同時啟用讀取和寫入 (表示檔案是要開啟以供「更新」之用)。 不過,當您從讀取切換為寫入時,輸入作業一定會遇到 EOF 標記。 如果沒有 EOF,您必須使用檔案定位函式的介入呼叫。 檔案定位函式包括 fsetposfseekrewind。 當您從寫入切換為讀取時,您必須使用 fflush 或檔案定位函式的介入呼叫。

除了先前的值之外,還可以將下列字元附加至 mode ,指定新行字元的轉譯模式。

mode 改 性 劑 翻譯模式
t 以文字 (已轉譯) 模式開啟。 歸位換行字元 (CR-LF) 組合會轉譯成輸入的單行摘要(LF),而 LF 字元則會轉譯為輸出上的 CR-LF 組合。 此外,Ctrl+Z 會在輸入中解譯成檔案結尾字元。
b 以二進位 (未轉譯) 模式開啟;隱藏涉及歸位字元和換行字元的翻譯。

在文字模式中, CTRL+ Z 會在輸入上解譯為 EOF 字元。 在使用 "a+" 開啟以供讀取/寫入的檔案中, fopen 檢查 CTRL+ 檔案結尾的 Z ,如果可能的話,就會將其移除。 因為使用 fseekftell 在以 CTRL+ Z 結尾的檔案內移動,所以移除它可能會導致 fseek 在檔案結尾處的行為不正確。

在文字模式中,歸位字元換行字元 (CRLF) 組合會轉譯成輸入上的單行摘要 (LF) 字元,而 LF 字元則會轉譯為輸出上的 CRLF 組合。 Unicode 資料流 I/O 函式在文字模式 (預設) 下運作時,會假設來源或目的資料流是多位元組字元的序列。 因此,Unicode 資料流輸入函式會將多位元組字元轉換為寬字元 (就像呼叫 mbtowc 函式一樣)。 基於相同的原因,Unicode 資料流輸出函式會將寬字元轉換為多位元組字元 (就像呼叫 wctomb 函式一樣)。

如果 tb 未在 中 mode 指定 ,則預設轉譯模式是由全域變數 _fmode 所定義。 如果引數前置 tb ,則函式失敗並傳回 NULL

如需如何在 Unicode 和多位元組資料流程 I/O 中使用文字和二進位模式的詳細資訊,請參閱 文字和二進位模式中的文字和二進位模式 檔案 I/O 和 Unicode 資料流程 I/O 。

您可以附加下列選項, mode 以指定更多行為。

mode 改 性 劑 行為
x 如果已經存在,強制函式失敗 filename 。 只能與 「w」 或 「w+」 規範搭配使用。
c 啟用關聯 filename 的認可旗標,以便在呼叫 fflush_flushall 時,將檔案緩衝區的內容直接寫入磁碟。
n 將關聯的 filename 認可旗標重設為 「無認可」。此旗標是預設值。 如果將程式與 COMMODE.OBJ 連結,也會覆寫全域認可旗標。 除非您明確連結程式與 COMMODE,否則全域認可旗標預設值為「無認可」。OBJ (請參閱 連結選項 )。
N 指定子進程不會繼承檔案。
S 指定針對但不限於磁碟的循序存取進行快取最佳化。
R 指定針對但不限於磁碟的隨機存取進行快取最佳化。
T 指定除非記憶體壓力需要它,否則不會寫入磁片的檔案。
D 指定關閉最後一個檔案指標時刪除的暫存檔。
ccs=encoding 指定要用於這個檔案的編碼字元集(其中 UTF-8 一個 、 UTF-16LEUNICODE )。 如果您想要使用 ANSI 編碼方式,請保持為未指定。 此旗標與前面加上逗號的旗標分隔。 , 例如:FILE *f = fopen("newfile.txt", "rt+, ccs=UTF-8");

用於 和 之 mode 字串的有效字元會對應至 oflag_sopen 中使用的 _open 引數, _fdopen 如下所示。 fopen

mode 字串中的字元 _open/_sopen 的對等 oflag
a _O_WRONLY | _O_APPEND (通常為 _O_WRONLY | _O_CREAT | _O_APPEND )
a+ _O_RDWR | _O_APPEND (通常為 _O_RDWR | _O_APPEND | _O_CREAT )
r _O_RDONLY
r+ _O_RDWR
w _O_WRONLY (通常為 _O_WRONLY | _O_CREAT | _O_TRUNC )
w+ _O_RDWR (通常為 _O_RDWR | _O_CREAT | _O_TRUNC )
b _O_BINARY
t _O_TEXT (翻譯)
x _O_EXCL
c
n
S _O_SEQUENTIAL
R _O_RANDOM
T _O_SHORTLIVED
D _O_TEMPORARY
ccs=UNICODE _O_WTEXT
*ccs=UTF-8* _O_UTF8
ccs=UTF-16LE _O_UTF16

如果您使用 rb 模式,則不需要移植程式碼,而且如果您預期會讀取大部分大型檔案或不關心網路效能,您可能也會考慮是否要使用記憶體對應的 Win32 檔案作為選項。

關於 TD

  • T 只要記憶體壓力不需要,就可避免將檔案寫入磁片。 如需詳細資訊,請參閱 FILE_ATTRIBUTE_TEMPORARY 檔案屬性常數 以及此部落格文章 它只是暫時性的
  • D 指定寫入磁片的一般檔案。 差異在於關閉時會自動刪除。 您可以結合 TD 以取得這兩個語意。

、、、、、 tTDmode 選項是 和 的 fopen_wfopen Microsoft 擴充功能,當您想要 ANSI 可攜性時,不應該使用 和 。 SRnc

需求

函式 必要的標頭
fopen <stdio.h>
_wfopen <stdio.h><wchar.h>

_wfopen 是 Microsoft 擴充功能。 如需相容性的詳細資訊,請參閱 相容性

、、、、、 RTDmode 選項是 和 _fdopenfopen Microsoft 延伸模組,而且不應該在需要 ANSI 可攜性的地方使用。 Stnc

範例 1

下列程式會開啟兩個檔案。 這會使用 fclose 關閉第一個檔案,並使用 _fcloseall 關閉所有剩下的檔案。

// crt_fopen.c
// compile with: /W3
// This program opens two files. It uses
// fclose to close the first file and
// _fcloseall to close all remaining files.

#include <stdio.h>

FILE *stream, *stream2;

int main( void )
{
   int numclosed;

   // Open for read (will fail if file "crt_fopen.c" does not exist)
   if( (stream  = fopen( "crt_fopen.c", "r" )) == NULL ) // C4996
   // Note: fopen is deprecated; consider using fopen_s instead
      printf( "The file 'crt_fopen.c' was not opened\n" );
   else
      printf( "The file 'crt_fopen.c' was opened\n" );

   // Open for write
   if( (stream2 = fopen( "data2", "w+" )) == NULL ) // C4996
      printf( "The file 'data2' was not opened\n" );
   else
      printf( "The file 'data2' was opened\n" );

   // Close stream if it is not NULL
   if( stream)
   {
      if ( fclose( stream ) )
      {
         printf( "The file 'crt_fopen.c' was not closed\n" );
      }
   }

   // All other files are closed:
   numclosed = _fcloseall( );
   printf( "Number of files closed by _fcloseall: %u\n", numclosed );
}
The file 'crt_fopen.c' was opened
The file 'data2' was opened
Number of files closed by _fcloseall: 1

範例 2

下列程式會在使用 Unicode 編碼方式的文字模式下建立檔案 (如果存在則覆寫)。 然後將兩個字串寫入檔案並關閉檔案。 輸出是名為 _wfopen_test.xml 的檔案,其中包含輸出區段中的資料。

// crt__wfopen.c
// compile with: /W3
// This program creates a file (or overwrites one if
// it exists), in text mode using Unicode encoding.
// It then writes two strings into the file
// and then closes the file.

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <wchar.h>

#define BUFFER_SIZE 50

int main(int argc, char** argv)
{
    wchar_t str[BUFFER_SIZE];
    size_t  strSize;
    FILE*   fileHandle;

    // Create an the xml file in text and Unicode encoding mode.
    if ((fileHandle = _wfopen( L"_wfopen_test.xml",L"wt+,ccs=UNICODE")) == NULL) // C4996
    // Note: _wfopen is deprecated; consider using _wfopen_s instead
    {
        wprintf(L"_wfopen failed!\n");
        return(0);
    }

    // Write a string into the file.
    wcscpy_s(str, sizeof(str)/sizeof(wchar_t), L"<xmlTag>\n");
    strSize = wcslen(str);
    if (fwrite(str, sizeof(wchar_t), strSize, fileHandle) != strSize)
    {
        wprintf(L"fwrite failed!\n");
    }

    // Write a string into the file.
    wcscpy_s(str, sizeof(str)/sizeof(wchar_t), L"</xmlTag>");
    strSize = wcslen(str);
    if (fwrite(str, sizeof(wchar_t), strSize, fileHandle) != strSize)
    {
        wprintf(L"fwrite failed!\n");
    }

    // Close the file.
    if (fclose(fileHandle))
    {
        wprintf(L"fclose failed!\n");
    }
    return 0;
}

另請參閱

資料流 I/O
多位元組字元序列的解譯
fclose, _fcloseall
_fdopen, _wfdopen
ferror
_fileno
freopen, _wfreopen
_open, _wopen
_setmode
_sopen, _wsopen