fopen_s、_wfopen_sfopen_s, _wfopen_s

打开文件。Opens a file. 这些版本的 fopen、_wfopen 具有安全增强功能,如 CRT 中的安全功能所述。These versions of fopen, _wfopen have security enhancements, as described in Security Features in the CRT.

语法Syntax

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   
);  

参数Parameters

[out] pFile[out] pFile
指向文件指针的指针,文件指针将接收指向已打开文件的指针。A pointer to the file pointer that will receive the pointer to the opened file.

[in] filename[in] filename
文件名。Filename.

[in] mode[in] mode
允许的访问类型。Type of access permitted.

返回值Return Value

如果成功,则为零;如果失败,则为错误代码。Zero if successful; an error code on failure. 有关这些错误代码的详细信息,请参阅 errno、_doserrno、_sys_errlist 和 _sys_nerrSee errno, _doserrno, _sys_errlist, and _sys_nerr for more information about these error codes.

错误条件Error Conditions

pFile filename mode 返回值Return Value pFile 的内容Contents of pFile
NULL 任何any 任何any EINVAL 未更改unchanged
任何any NULL 任何any EINVAL 未更改unchanged
任何any 任何any NULLNULL EINVAL 未更改unchanged

备注Remarks

通过 fopen_s_wfopen_s 打开的文件不可共享。Files that are opened by fopen_s and _wfopen_s are not sharable. 如果要求文件可共享,请将 _fsopen、_wfsopen 与相应的共享模式常量(例如用于读/写共享的 _SH_DENYNO)一起使用。If you require that a file be sharable, use _fsopen, _wfsopen with the appropriate sharing mode constant—for example, _SH_DENYNO for read/write sharing.

fopen_s 函数将打开 filename 指定的文件。The fopen_s function opens the file that's specified by filename. _wfopen_sfopen_s 的宽字符版本;_wfopen_s 的参数是宽字符串。_wfopen_s is a wide-character version of fopen_s; the arguments to _wfopen_s are wide-character strings. 除此以外,_wfopen_sfopen_s 的行为完全相同。_wfopen_s and fopen_s behave identically otherwise.

fopen_s 接受执行时文件系统上有效的路径;fopen_s 接受 UNC 路径以及包含所映射网络驱动器的路径,前提是执行代码的系统在执行时能够访问共享或映射的网络驱动器。fopen_s accepts paths that are valid on the file system at the point of execution; UNC paths and paths that involve mapped network drives are accepted by fopen_s as long as the system that's executing the code has access to the share or mapped network drive at the time of execution. fopen_s 构造路径时,请勿做出有关驱动器、路径或执行环境中网络共享的可用性假设。When you construct paths for fopen_s, don't make assumptions about the availability of drives, paths, or network shares in the execution environment. 可使用斜杠 (/) 或反斜杠 (\) 作为路径中的目录分隔符。You can use either forward slashes (/) or backslashes (\) as the directory separators in a path.

这些函数验证其参数。These functions validate their parameters. 如果 pFilefilenamemode 为 null 指针,则这些函数将生成无效的参数异常,如参数验证中所述。If pFile, filename, or mode is a null pointer, these functions generate an invalid parameter exception, as described in Parameter Validation.

请始终先检查返回值,确定该函数是否成功,再对文件执行任何进一步的操作。Always check the return value to see if the function succeeded before you perform any further operations on the file. 如果出现错误,则将返回错误代码并且将设置全局变量 errnoIf an error occurs, the error code is returned and the global variable errno is set. 有关详细信息,请参阅 errno、_doserrno、_sys_errlist 和 _sys_nerrFor more information, see errno, _doserrno, _sys_errlist, and _sys_nerr.

Unicode 支持Unicode support

fopen_s 支持 Unicode 文件流。fopen_s supports Unicode file streams. 若要打开新的或现有的 Unicode 文件,请将指定所需编码的 ccs 标志传递到 fopen_sTo open a new or existing Unicode file, pass a ccs flag that specifies the desired encoding to fopen_s:

fopen_s(&fp, "newfile.txt", "rw, ccs=编码");fopen_s(&fp, "newfile.txt", "rw, ccs=encoding");

允许的值的编码UNICODEUTF-8,和UTF-16LEAllowed values of encoding are UNICODE, UTF-8, and UTF-16LE. 如果存在为不指定任何值编码fopen_s使用 ANSI 编码。If there no value is specified for encoding, fopen_s uses ANSI encoding.

如果文件已存在并已打开以进行读取或追加,则字节顺序标记 (BOM)(如果文件中存在)将确定编码。If the file already exists and is opened for reading or appending, the Byte Order Mark (BOM), if present in the file, determines the encoding. BOM 编码优先于 ccs 标志指定的编码。The BOM encoding takes precedence over the encoding that's specified by the ccs flag. 仅在不存在 BOM 或如果文件是新文件时,才使用 ccs 编码。The ccs encoding is only used when no BOM is present or if the file is a new file.

备注

BOM 检测仅适用于在 Unicode 模式下打开的文件;即,通过传递 ccs 标志打开的文件。BOM-detection only applies to files that are opened in Unicode mode; that is, by passing the ccs flag.

下表汇总了提供给 fopen_s 的各种 ccs 标志的模式以及文件中字节顺序标记的模式。The following table summarizes the modes for various ccs flags that are given to fopen_s and for Byte Order Marks in the file.

基于 ccs 标志和 BOM 使用的编码Encodings Used Based on ccs Flag and BOM

ccs 标志ccs flag 无 BOM(或新文件)No BOM (or new file) BOM:UTF-8BOM: UTF-8 BOM:UTF-16BOM: 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。Files that are opened for writing in Unicode mode have a BOM written to them automatically.

如果mode是",ccs =编码",fopen_s首先尝试使用读取访问权限和写访问权限打开文件。If mode is "a, ccs=encoding", fopen_s first tries to open the file with both read access and write access. 如果成功,此函数将读取 BOM 以确定文件的编码;如果失败,此函数将使用文件的默认编码。If successful, the function reads the BOM to determine the encoding for the file; if unsuccessful, the function uses the default encoding for the file. 在任一情况下,fopen_s 随后均将使用只写访问权限打开文件。In either case, fopen_s then re-opens the file with write-only access. (这仅适用于a 模式,不适用于 a+。)(This applies to a mode only, not a+.)

一般文本例程映射Generic-Text Routine Mappings

TCHAR.H 例程TCHAR.H routine 未定义 _UNICODE 和 _MBCS_UNICODE & _MBCS not defined 已定义 _MBCS_MBCS defined 已定义 _UNICODE_UNICODE defined
_tfopen_s fopen_s fopen_s _wfopen_s

字符串 mode 指定对文件请求的访问类型,如下所示。The character string mode specifies the kind of access that's requested for the file, as follows.

"r"
打开以便读取。Opens for reading. 如果文件不存在或找不到,fopen_s 调用将失败。If the file does not exist or cannot be found, the fopen_s call fails.

"w"
打开用于写入的空文件。Opens an empty file for writing. 如果文件存在,则其内容会被销毁。If the file exists, its contents are destroyed.

"a"
在文件末尾打开以进行写入(追加),在将新数据写入到文件之前请勿删除 EOF 标记。Opens for writing at the end of the file (appending) without removing the EOF marker before writing new data to the file. 如果文件不存在,则创建文件。Creates the file if it doesn't exist.

"r+"
打开以便读取和写入。Opens for both reading and writing. (该文件必须存在。)(The file must exist.)

"w+"
打开用于读取和写入的空文件。Opens an empty file for both reading and writing. 如果文件存在,则其内容会被销毁。If the file exists, its contents are destroyed.

"a+"
打开以进行读取和追加。Opens for reading and appending. 追加操作包括在将新数据写入文件之前删除 EOF 标记并在写入完成后还原 EOF 标记。The appending operation includes the removal of the EOF marker before new data is written to the file and the EOF marker is restored after writing is complete. 如果文件不存在,则创建文件。Creates the file if it doesn't exist.

通过使用 "a""a+" 访问类型打开文件时,所有写入操作均将在文件末尾进行。When a file is opened by using the "a" or "a+" access type, all write operations occur at the end of the file. 使用 fseekrewind 可重新定位文件指针,但在执行任何写入操作前,文件指针将始终被移回文件末尾,以确保不会覆盖现有数据。The file pointer can be repositioned by using fseek or rewind, but it's always moved back to the end of the file before any write operation is carried out so that existing data cannot be overwritten.

在 EOF 标记追加到文件之前,"a" 模式不会将其删除。The "a" mode does not remove the EOF marker before appending to the file. 追加后,MS-DOS TYPE 命令仅显示原始 EOF 标记之前的数据,不显示追加到文件的任何数据。After appending has occurred, the MS-DOS TYPE command only shows data up to the original EOF marker and not any data that's appended to the file. 在 EOF 标记追加到文件之前,"a+" 模式会将其删除。The "a+" mode does remove the EOF marker before appending to the file. 在追加后,MS-DOS TYPE 命令显示文件中的所有数据。After appending, the MS-DOS TYPE command shows all data in the file. 需使用 "a+" 模式才能追加到使用 CTRL+Z EOF 标记终止的流文件。The "a+" mode is required for appending to a stream file that is terminated by using the CTRL+Z EOF marker.

"r+""w+","a+"指定访问类型,允许读取和写入。When the "r+", "w+", or "a+" access type is specified, both reading and writing are allowed. (文件将处于打开状态以进行“更新”。)但是,当你从读取切换到写入时,输入操作必须遇到 EOF 标记。(The file is said to be open for "update".) However, when you switch from reading to writing, the input operation must encounter an EOF marker. 如果没有 EOF,必须使用对文件定位函数的干预调用。If there is no EOF, you must use an intervening call to a file-positioning function. 文件定位函数是 fsetposfseekrewindThe file-positioning functions are fsetpos, fseek, and rewind. 从写入切换到读取时,必须使用对 fflush 或文件定位函数的干预调用。When you switch from writing to reading, you must use an intervening call to either fflush or to a file-positioning function.

除了以上值之外,可以在 mode 中包含以下字符以指定换行符的转换模式:In addition to the above values, the following characters can be included in mode to specify the translation mode for newline characters:

t
在文本(转换)模式下打开。Open in text (translated) mode. 在此模式中,CTRL+Z 将在输入时解释为文件尾字符。In this mode, CTRL+Z is interpreted as an end-of-file character on input. 在打开使用 "a+" 进行读取/写入的文件中,fopen_s 将检查文件末尾的 Ctrl+Z 并在可能的情况下将其删除。In files opened for reading/writing with "a+", fopen_s checks for a CTRL+Z at the end of the file and removes it, if possible. 这是因为使用 fseekftell 在以 CTRL+Z 结尾的文件中移动时,可能会导致 fseek 在文件末尾附近运行不当。This is done because using fseek and ftell to move within a file that ends with a CTRL+Z, may cause fseek to behave improperly near the end of the file.

此外,在文本模式下回车换行符组合将转换为单一的换行输入,并换行字符将转换为输出回车返回换行组合。Also, in text mode, carriage return-linefeed combinations are translated into single linefeeds on input, and linefeed characters are translated to carriage return-linefeed combinations on output. 当 Unicode 流 I/O 函数在文本模式(默认设置)下运行时,源或目标流将假定为一系列多字节字符。When a Unicode stream-I/O function operates in text mode (the default), the source or destination stream is assumed to be a sequence of multibyte characters. 因此,Unicode 流输入函数将多字节字符转换为宽字符(就像调用 mbtowc 函数一样)。Therefore, the Unicode stream-input functions convert multibyte characters to wide characters (as if by a call to the mbtowc function). 出于同一原因,Unicode 流输出函数将宽字符转换为多字节字符(就像调用 wctomb 函数一样)。For the same reason, the Unicode stream-output functions convert wide characters to multibyte characters (as if by a call to the wctomb function).

b
在二进制(未转换)模式下打开;不进行涉及回车和换行字符的转换。Open in binary (untranslated) mode; translations involving carriage-return and linefeed characters are suppressed.

如果 tbmode中未给出,则默认转换模式由全局变量 _fmode定义。If t or b is not given in mode, the default translation mode is defined by the global variable _fmode. 如果 tb 是该参数的前缀,则函数将失败并返回 NULLIf t or b is prefixed to the argument, the function fails and returns NULL.

有关在 Unicode 和多字节流 I/O 中使用文本和二进制模式的详细信息,请参阅文本和二进制模式文件 I/O文本和二进制模式下的 Unicode 流 I/OFor more information about using text and binary modes in Unicode and multibyte stream-I/O, see Text and Binary Mode File I/O and Unicode Stream I/O in Text and Binary Modes.

c
启用关联 filename 的提交标志,以便在调用 fflush_flushall 时将文件缓冲区的内容直接写入磁盘。Enable the commit flag for the associated filename so that the contents of the file buffer are written directly to disk if either fflush or _flushall is called.

n
将关联 filename 的提交标志重置为“no-commit”。Reset the commit flag for the associated filename to "no-commit." 这是默认设置。This is the default. 如果将程序显式链接到 COMMODE.OBJ,它还将重写全局提交标志。It also overrides the global commit flag if you link your program with COMMODE.OBJ. 除非将程序显式链接到 COMMODE.OBJ,否则全局提交标志默认为“no-commit”(请参阅 Link Options)。The global commit flag default is "no-commit" unless you explicitly link your program with COMMODE.OBJ (see Link Options).

N
指定文件不由子进程继承。Specifies that the file is not inherited by child processes.

S
指定缓存针对(但不限于)从磁盘的顺序访问进行优化。Specifies that caching is optimized for, but not restricted to, sequential access from disk.

R
指定缓存针对(但不限于)从磁盘的随机访问进行优化。Specifies that caching is optimized for, but not restricted to, random access from disk.

T
将文件指定为临时。Specifies a file as temporary. 如果可能,它不会刷新到磁盘。If possible, it is not flushed to disk.

D
将文件指定为临时。Specifies a file as temporary. 最后一个文件指针关闭时,它将被删除。It is deleted when the last file pointer is closed.

ccs=ENCODING
指定此文件使用的编码字符集 (UTF-8、UTF-16LE 和 UNICODE)。Specify the coded character set to use (UTF-8, UTF-16LE, and UNICODE) for this file. 如果需要 ANSI 编码,请保留此选项不指定。Leave this unspecified if you want ANSI encoding.

fopen_s_fdopen 中使用的 mode 字符串的有效字符对应于在 _open_sopen 中使用的 oflag 参数。Valid characters for the mode string used in fopen_s and _fdopen correspond to oflag arguments used in _open and _sopen, as follows.

模式字符串中的字符Characters in mode string _open/_sopen 的等效 oflagEquivalent oflag value for _open/_sopen
a _O_WRONLY | _O_APPEND(通常为 _O_WRONLY | _O_CREAT | _O_APPEND_O_WRONLY | _O_APPEND (usually _O_WRONLY | _O_CREAT | _O_APPEND)
a+ _O_RDWR | _O_APPEND (通常为 _O_RDWR | _O_APPEND | _O_CREAT_O_RDWR | _O_APPEND (usually _O_RDWR | _O_APPEND | _O_CREAT )
r _O_RDONLY
r+ _O_RDWR
w _O_WRONLY (通常为 _O_WRONLY | _O_CREAT | _O_TRUNC_O_WRONLY (usually _O_WRONLY | _O_CREAT | _O_TRUNC)
w+ _O_RDWR (通常为 _O_RDWR | _O_CREAT | _O_TRUNC_O_RDWR (usually _O_RDWR | _O_CREAT | _O_TRUNC)
b _O_BINARY
t _O_TEXT
c None
n None
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 文件可能也是一个选项。If you are using rb mode, won't need to port your code, and expect to read a lot of the file and/or don't care about network performance, memory mapped Win32 files might also be an option.

惠?Requirements

函数Function 必需的标头Required header
fopen_s <stdio.h><stdio.h>
_wfopen_s <stdio.h> 或 <wchar.h><stdio.h> or <wchar.h>

有关其他兼容性信息,请参见“简介”中的 兼容性For additional compatibility information, see Compatibility in the Introduction.

Libraries

C 运行时库的所有版本。All versions of the C run-time libraries.

cnt mode 选项是 fopen_s_fdopen 的 Microsoft 扩展,不应在需要 ANSI 可移植性时使用。The c, n, and t mode options are Microsoft extensions for fopen_s and _fdopen and should not be used where ANSI portability is desired.

示例Example

// 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" does not 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+" );  
   if( err == 0 )  
   {  
      printf( "The file 'data2' was opened\n" );  
   }  
   else  
   {  
      printf( "The file 'data2' was not opened\n" );  
   }  

   // Close stream if it is not 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  

请参阅See Also

流 I/O Stream I/O
fclose、_fcloseall fclose, _fcloseall
_fdopen、_wfdopen _fdopen, _wfdopen
ferror ferror
_fileno _fileno
freopen、_wfreopen freopen, _wfreopen
_open、_wopen _open, _wopen
_setmode_setmode