fopen_s
, _wfopen_s
開啟檔案。 這些版本的 fopen
具有_wfopen
安全性增強功能,如CRT中的安全性功能中所述。
語法
errno_t fopen_s(
FILE** pFile,
const char *filename,
const char *mode
);
errno_t _wfopen_s(
FILE** pFile,
const wchar_t *filename,
const wchar_t *mode
);
參數
pFile
接收已開啟檔案指標之檔案指標的指標。
filename
要開啟之檔案的名稱。
mode
允許的存取類型。
傳回值
如果成功,就是零,如果失敗,則為錯誤碼。 如需這些錯誤碼的詳細資訊,請參閱errno
、 _doserrno
_sys_errlist
和 _sys_nerr
。
錯誤條件
pFile |
filename |
mode |
傳回值 | pFile 的內容。 |
---|---|---|---|---|
NULL |
任意 | 任意 | EINVAL |
未變更 |
任意 | NULL |
任意 | EINVAL |
未變更 |
任意 | 任意 | NULL |
EINVAL |
未變更 |
備註
和 _wfopen_s
函fopen_s
式無法開啟檔案以供共用。 如果您需要共用檔案,請使用 _fsopen
或 _wfsopen
搭配適當的共用模式常數,例如,用於 _SH_DENYNO
讀取/寫入共用。
函 fopen_s
式會開啟 所 filename
指定的檔案。 _wfopen_s
是的寬字元版本 fopen_s
,而的 _wfopen_s
自變數為寬字元字串。 _wfopen_s
或 fopen_s
相同,否則為 。
fopen_s
接受執行之時在檔案系統上為有效的路徑;fopen_s
接受 UNC 路徑以及包含對應的網路磁碟機的路徑,只要執行程式碼的系統在執行時有權存取共用或對應的網路磁碟機即可。 當您建構 fopen_s
的路徑時,請不要假設磁碟機、路徑或網路共用在執行環境中可供使用。 您可以使用正斜線 (/) 或反斜杠 (\) 作為路徑中的目錄分隔符。
這些函式會驗證它們的參數。 如果 pFile
、 filename
或 mode
是 Null 指標,這些函式會產生無效的參數例外狀況,如參數驗證中所述。
請務必檢查傳回值,以查看函式是否成功,再對檔案執行任何進一步的作業。 如果發生錯誤,則會傳回錯誤碼,並設定全域變數 errno
。 如需詳細資訊,請參閱errno
, _doserrno
, _sys_errlist
和_sys_nerr
.
根據預設,此函式的全域狀態會限定於應用程式。 若要變更它,請參閱 CRT中的全域狀態。
Unicode 支援
fopen_s
支援 Unicode 檔案資料流。 若要開啟新的或現有的 Unicode 檔案,請將指定所需編碼的旗標傳遞 ccs
至 fopen_s
,例如:
fopen_s(&fp, "newfile.txt", "w+, ccs=UNICODE");
旗標的UNICODE
ccs
允許值為、 UTF-8
與 UTF-16LE
。 如果未為 ccs
指定任何值, fopen_s
請使用 ANSI 編碼。
如果檔案已經存在且已開啟以進行讀取或附加,則如果檔案中存在,則位元組順序標記 (BOM)會決定編碼方式。 BOM 編碼方式的優先順序高於 ccs
旗標所指定的編碼方式。 當 BOM 不存在或如果檔案為新檔案時,只能使用 ccs
編碼方式。
注意
BOM 偵測只適用於以 Unicode 模式 (也就是透過傳遞 ccs
旗標) 開啟的檔案。
下表摘要說明檔案中提供給fopen_s
和 BOM 之各種ccs
旗標值的模式。
根據 ccs
旗標和 BOM 使用的編碼
ccs 旗標 |
沒有 BOM (或新檔案) | BOM:UTF-8 | BOM:UTF-16 |
---|---|---|---|
UNICODE |
UTF-8 |
UTF-8 |
UTF-16LE |
UTF-8 |
UTF-8 |
UTF-8 |
UTF-16LE |
UTF-16LE |
UTF-16LE |
UTF-8 |
UTF-16LE |
開啟以供在 Unicode 模式下寫入的檔案會有 BOM 自動寫入其中。
如果 mode
是 "a, ccs=UNICODE"
、 "a, ccs=UTF-8"
或 "a, ccs=UTF-16LE"
, fopen_s
則先嘗試開啟具有讀取存取權和寫入存取權的檔案。 如果成功,則函式會讀取 BOM 以判斷檔案的編碼方式,如果不成功,則函式會使用檔案的預設編碼方式。 在這兩種情況下, fopen_s
然後重新開啟具有唯寫存取權的檔案。 (此行為 a
僅適用於模式,不適用於 a+
。
字元字串 mode
會指定對檔案要求的存取類型,如下所示。
mode |
存取 |
---|---|
"r" |
開啟以讀取。 如果檔案不存在或找不到,呼叫 fopen_s 就會失敗。 |
"w" |
開啟空白檔案以寫入。 如果指定的檔案已存在,其內容將被終結。 |
"a" |
開啟以供在檔案結尾寫入 (附加),並且在將新資料寫入檔案之前,不會移除檔案結尾 (EOF) 標記。 如果該檔案不存在,則建立檔案。 |
"r+" |
開啟以進行讀取和寫入。 檔案必須存在。 |
"w+" |
開啟空白檔案以進行讀取和寫入。 如果檔案存在,其內容會遭到銷毀。 |
"a+" |
開啟以進行讀取和附加。 附加作業包括在將新資料寫入檔案之前移除 EOF 標記。 寫入完成後,不會還原 EOF 標記。 如果該檔案不存在,則建立檔案。 |
使用 "a"
或 "a+"
存取類型開啟檔案時,所有寫入作業都會在檔案結尾進行。 檔案指標可以使用 或 rewind
來重新置放fseek
,但在執行任何寫入作業之前,一律會移回檔案的結尾,以便無法覆寫現有的數據。
在 "a"
附加至檔案之前,模式不會移除 EOF 標記。 發生附加之後,MS-DOS TYPE
命令只會顯示原始 EOF 標記的數據,而不會顯示附加至檔案的任何數據。 在附加到檔案之前,"a+"
模式會移除 EOF 標記。 附加之後,MS-DOS TYPE
命令會顯示檔案中的所有數據。 附加"a+"
至以 Z EOF 標記終止的CTRL
+數據流檔案時,需要模式。
"r+"
指定、 "w+"
或 "a+"
存取類型時,允許讀取和寫入。 (據說檔案為開放進行“更新”。不過,當您從讀取切換為寫入時,輸入作業必須遇到 EOF 標記。 如果沒有 EOF 標記,您必須使用檔案定位函式的介入呼叫。 檔案定位函式包含 fsetpos
、fseek
和 rewind
。 當您從寫入切換為讀取時,您必須使用 fflush
或檔案定位函式的介入呼叫。
從 C11 開始,您可以在 檔案存在時附加 "x"
或 "w+"
"w"
導致函式失敗,而不是覆寫它。
除了先前的值之外,還可以包含 mode
下列字元,以指定換行符的翻譯模式:
mode 修飾元 |
翻譯模式 |
---|---|
t |
以文字 (已轉譯) 模式開啟。 歸位換行字元 (CR-LF) 組合會轉譯成輸入的單行摘要(LF),而 LF 字元則會轉譯為輸出上的 CR-LF 組合。 CTRL+Z 會在輸入時解譯為檔尾字元。 |
b |
以二進位 (未轉譯) 模式開啟;隱藏涉及歸位字元和換行字元的翻譯。 |
在文字(翻譯)模式中, CTRL
+Z 會在輸入時解譯為檔尾字元。 針對以 開啟以供讀取/寫入"a+"
的檔案,fopen_s
請盡可能檢查CTRL
+檔案結尾的 Z 並移除它。 因為使用 fseek
和 ftell
在以 CTRL
+Z 結尾的檔案內移動,所以移除它可能會導致 fseek
在檔案結尾處的行為不正確。
此外,在文字模式中,歸位字元/換行字元 (CRLF) 組合會轉譯成輸入上的單行摘要 (LF) 字元,而 LF 字元則會轉譯為輸出上的 CRLF 組合。 Unicode 資料流 I/O 函式在文字模式 (預設) 下運作時,會假設來源或目的資料流是多位元組字元的序列。 Unicode 數據流輸入函式會將多位元組字元轉換成寬字元(如同透過呼叫 函 mbtowc
式一樣)。 基於相同的原因,Unicode 資料流輸出函式會將寬字元轉換為多位元組字元 (就像呼叫 wctomb
函式一樣)。
如果 t
或 b
未在 中 mode
指定 ,則預設轉譯模式是由全域變數 _fmode
所定義。 如果引數前置 t
或 b
,則函式失敗並傳回 NULL
。
如需在 Unicode 和多位元組 stream-I/O 中使用文字和二進位模式的詳細資訊,請參閱文字和二進位模式中的文字和二進位模式檔案 I/O 和 Unicode 數據流 I/O。
mode 修飾元 |
行為 |
---|---|
c |
啟用關聯 filename 的認可旗標,以便在呼叫 fflush 或 _flushall 時,將檔案緩衝區的內容直接寫入磁碟。 |
n |
將關聯的 filename 認可旗標重設為 「無認可」。此旗標是預設值。 如果您將程序連結至 COMMODE.OBJ ,它也會覆寫全域認可旗標。 全域認可旗標預設值為「無認可」,除非您明確連結程式 COMMODE.OBJ (請參閱 連結選項)。 |
N |
指定子進程不會繼承檔案。 |
S |
指定針對但不限於磁碟的循序存取進行快取最佳化。 |
R |
指定針對但不限於磁碟的隨機存取進行快取最佳化。 |
T |
指定除非記憶體壓力需要它,否則不會寫入磁碟的檔案。 |
D |
指定關閉最後一個檔案指標時刪除的暫存盤。 |
ccs=UNICODE |
將 UNICODE 指定為要用於此檔案的編碼字元集。 如果您想要使用 ANSI 編碼方式,請保持為未指定。 |
ccs=UTF-8 |
將UTF-8指定為要用於此檔案的編碼字元集。 如果您想要使用 ANSI 編碼方式,請保持為未指定。 |
ccs=UTF-16LE |
指定UTF-16LE作為要用於此檔案的編碼字元集。 如果您想要使用 ANSI 編碼方式,請保持為未指定。 |
和中使用的_fdopen
fopen_s
字串的有效字元mode
會對應至 oflag
和 _sopen
中使用的_open
自變數,如下所示。
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 (翻譯) |
c |
無 |
n |
無 |
D |
_O_TEMPORARY |
R |
_O_RANDOM |
S |
_O_SEQUENTIAL |
T |
_O_SHORTLIVED |
ccs=UNICODE |
_O_WTEXT |
ccs=UTF-8 |
_O_UTF8 |
ccs=UTF-16LE |
_O_UTF16 |
t
、、、、、、 T
和mode
D
選項Microsoft ,fopen_s
而且當您想要 ANSI 可移植性時,不應該使用 和 。n
S
R
c
_wfopen_s
如果您使用 rb
模式,如果您不需要移植程式代碼,記憶體對應的 Win32 檔案也可能是一個選項,您預期會讀取大部分的檔案,或您不在意網路效能。
關於 T
與 D
:
T
只要記憶體壓力不需要,就可避免將檔案寫入磁碟。 如需詳細資訊,請參閱FILE_ATTRIBUTE_TEMPORARY
檔案屬性常數,以及此部落格文章它只是暫時性的。D
指定寫入磁碟的一般檔案。 差異在於關閉時會自動刪除。 您可以結合TD
以取得這兩個語意。
需求
函式 | 必要的標頭 | C++ 標頭 |
---|---|---|
fopen_s |
<stdio.h> |
<cstdio> |
_wfopen_s |
<stdio.h> 或 <wchar.h> |
<cstdio> |
如需 C 運行時間連結庫中標準一致性和命名慣例的詳細資訊,請參閱 相容性。
一般文字常式對應
<tchar.h> 常式 |
_UNICODE 和 _MBCS 未定義 |
_MBCS 已定義 |
_UNICODE 已定義 |
---|---|---|---|
_tfopen_s |
fopen_s |
fopen_s |
_wfopen_s |
程式庫
所有版本的 C 執行階段程式庫。
範例
// crt_fopen_s.c
// 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 )
{
errno_t err;
// Open for read (will fail if file "crt_fopen_s.c" doesn't exist)
err = fopen_s( &stream, "crt_fopen_s.c", "r" );
if( err == 0 )
{
printf( "The file 'crt_fopen_s.c' was opened\n" );
}
else
{
printf( "The file 'crt_fopen_s.c' was not opened\n" );
}
// Open for write
err = fopen_s( &stream2, "data2", "w+, ccs=UTF-8" );
if( err == 0 )
{
printf( "The file 'data2' was opened\n" );
}
else
{
printf( "The file 'data2' was not opened\n" );
}
// Close stream if it isn't NULL
if( stream )
{
err = fclose( stream );
if ( err == 0 )
{
printf( "The file 'crt_fopen_s.c' was closed\n" );
}
else
{
printf( "The file 'crt_fopen_s.c' was not closed\n" );
}
}
// All other files are closed:
int numclosed = _fcloseall( );
printf( "Number of files closed by _fcloseall: %u\n", numclosed );
}
The file 'crt_fopen_s.c' was opened
The file 'data2' was opened
Number of files closed by _fcloseall: 1
另請參閱
資料流 I/O
fclose
, _fcloseall
_fdopen
, _wfdopen
ferror
_fileno
freopen
, _wfreopen
_open
, _wopen
_setmode