fopen、_wfopenfopen, _wfopen

打开文件。Opens a file. 这些执行附加参数验证并返回错误代码的函数有更安全的版本可用;请参阅 fopen_s、_wfopen_sMore-secure versions of these functions that perform additional parameter validation and return error codes are available; see fopen_s, _wfopen_s.


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


文件名。File name.

启用的访问类型。Kind of access that's enabled.

返回值Return Value

这些函数均返回指向打开文件的指针。Each of these functions returns a pointer to the open file. 一个 null 指针值指示错误。A null pointer value indicates an error. 如果 filenamemodeNULL 或空字符串,这些函数则会触发无效的参数处理程序,如 Parameter ValidationIf filename or mode is NULL or an empty string, these functions trigger the invalid parameter handler, which is described in Parameter Validation. 如果允许执行继续,则这些函数将返回 NULL 并将 errno 设置为 EINVALIf execution is allowed to continue, these functions return NULL and set errno to EINVAL.

有关详细信息,请参阅 errno、_doserrno、_sys_errlist 和 _sys_nerrFor more information, see errno, _doserrno, _sys_errlist, and _sys_nerr.


fopen 函数打开 filename指定的文件。The fopen function opens the file that is specified by filename. 默认情况下,使用 ANSI 代码页 (CP_ACP) 解释窄 filename 字符串。By default, a narrow filename string is interpreted using the ANSI codepage (CP_ACP). 在 Windows 桌面应用程序中,可以通过使用 SetFileApisToOEM 函数将此更改为 OEM 代码页 (CP_OEMCP)。In Windows Desktop applications this can be changed to the OEM codepage (CP_OEMCP) by using the SetFileApisToOEM function. 可以使用 AreFileApisANSI 函数来确定是使用 ANSI 还是系统默认的 OEM 代码页来解释 filenameYou can use the AreFileApisANSI function to determine whether filename is interpreted using the ANSI or the system default OEM codepage. _wfopenfopen的宽字符版本; _wfopen 的参数是宽字符串。_wfopen is a wide-character version of fopen; the arguments to _wfopen are wide-character strings. 除此以外, _wfopenfopen 的行为完全相同。Otherwise, _wfopen and fopen behave identically. 仅使用 _wfopen 不会影响在文件流中使用的编码字符集。Just using _wfopen does not affect the coded character set that is used in the file stream.

fopen 接受执行时在文件系统上有效的路径; fopen 还接受 UNC 路径和包含映射的网络驱动器的路径(前提是执行代码的系统在执行时能够访问共享或映射的驱动器)。fopen accepts paths that are valid on the file system at the point of execution; fopen accepts UNC paths and paths that involve mapped network drives as long as the system that executes the code has access to the share or mapped drive at the time of execution. fopen构造路径时,请确保驱动器、路径或网络共享在执行环境中可用。When you construct paths for fopen, make sure that drives, paths, or network shares will be available in the execution environment. 可使用斜杠 (/) 或反斜杠 (\) 作为路径中的目录分隔符。You can use either forward slashes (/) or backslashes (\) as the directory separators in a path.

对文件执行任何其他操作前,请始终检查返回值以确定指针是否为 NULL。Always check the return value to see whether the pointer is NULL before you perform any additional operations on the file. 如果发生错误,系统将设置全局变量 errno ,此变量可用于获取特定错误信息。If an error occurs, the global variable errno is set and may be used to obtain specific error information. 有关详细信息,请参阅 errno、_doserrno、_sys_errlist 和 _sys_nerrFor more information, see errno, _doserrno, _sys_errlist, and _sys_nerr.

Unicode 支持Unicode Support

fopen 支持 Unicode 文件流。fopen supports Unicode file streams. 若要打开 Unicode 文件,请将指定所需编码的 ccs 标志传递到 fopen,如下所示。To open a Unicode file, pass a ccs flag that specifies the desired encoding to fopen, as follows.

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

允许使用的 encoding 值为 UNICODEUTF-8UTF-16LEAllowed values of encoding are UNICODE, UTF-8, and UTF-16LE.

在 Unicode 模式下打开文件时,输入函数会将从文件中读取的数据转换为存储为 wchar_t类型的 UTF-16 数据。When a file is opened in Unicode mode, input functions translate the data that's read from the file into UTF-16 data stored as type wchar_t. 写入到在 Unicode 模式下打开的文件的函数需要包含存储为 wchar_t类型的 UTF-16 数据的缓冲区。Functions that write to a file opened in Unicode mode expect buffers that contain UTF-16 data stored as type wchar_t. 如果将文件编码为 UTF-8,则在写入它时,UTF-16 数据会转换为 UTF-8;在读取它时,该文件的 UTF-8 编码的内容会转换为 UTF-16。If the file is encoded as UTF-8, then UTF-16 data is translated into UTF-8 when it is written, and the file's UTF-8-encoded content is translated into UTF-16 when it is read. 尝试在 Unicode 模式下读取或写入奇数个字节会导致 参数验证 错误。An attempt to read or write an odd number of bytes in Unicode mode causes a parameter validation error. 若要读取或写入在你的程序中存储为 UTF-8 的数据,请使用文本或二进制文件模式,而不是 Unicode 模式。To read or write data that's stored in your program as UTF-8, use a text or binary file mode instead of a Unicode mode. 你应负责所有必需的编码转换。You are responsible for any required encoding translation.

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

下表汇总的模式用于传递到文件中的 ccs 和字节顺序标记的各种 fopen 标志。The following table summarizes the modes that are used for various ccs flags given to fopen and 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 模式下打开以进行写入的文件将自动写入 BOM。Files opened for writing in Unicode mode have a BOM written to them automatically.

如果 mode 为“a, ccs=<encoding>”, fopen 将先尝试使用读取和写入访问权限打开文件。If mode is "a, ccs=<encoding>", fopen first tries to open the file by using both read and write access. 如果成功,此函数将读取 BOM 以确定文件的编码;如果失败,此函数将使用文件的默认编码。If this succeeds, the function reads the BOM to determine the encoding for the file; if this fails, the function uses the default encoding for the file. 无论何种情况, fopen 随后均将使用只写访问权限打开文件。In either case, fopen will then re-open the file by using write-only access. (这仅适用于 a 模式,不适用于 a+ 模式。)(This applies to a mode only, not to a+ mode.)

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

TCHAR.H 例程TCHAR.H routine 未定义 _UNICODE 和 _MBCS_UNICODE & _MBCS not defined 已定义 _MBCS_MBCS defined 已定义 _UNICODE_UNICODE defined
_tfopen fopen fopen _wfopen

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

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

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

在文件末尾打开以进行写入(追加),在新数据写入到文件之前不移除文件末尾 (EOF) 标记。Opens for writing at the end of the file (appending) without removing the end-of-file (EOF) marker before new data is written to the file. 创建文件(如果文件不存在)。Creates the file if it does not exist.

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

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

打开以进行读取和追加。Opens for reading and appending. 追加操作包括在新数据写入文件之前移除 EOF 标记。The appending operation includes the removal of the EOF marker before new data is written to the file. 写入完成后,EOF 标记不会还原。The EOF marker is not restored after writing is completed. 创建文件(如果文件不存在)。Creates the file if it does not exist.

使用 "a" 访问类型或 "a+" 访问类型打开文件时,所有写入操作均将在文件末尾进行。When a file is opened by using the "a" access type or the "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 is always moved back to the end of the file before any write operation is performed. 因此,无法覆盖现有数据。Therefore, existing data cannot be overwritten.

在 EOF 标记追加到文件之前, "a" 模式不会将其移除。The "a" mode does not remove the EOF marker before it appends 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 appended to the file. EOF 标记追加到文件之前, "a+" 模式不会将其移除。Before it appends to the file, the "a+" mode does remove the EOF marker. 在追加后,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 with the CTRL+Z EOF marker.

指定 "r+""w+""a+" 访问类型时,允许读取和写入(文件将处于打开状态以进行“更新”)。When the "r+", "w+", or "a+" access type is specified, both reading and writing are enabled (the file is said to be open for "update"). 但是,当你从读取切换到写入时,输入操作必须遇到 EOF 标记。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 earlier values, the following characters can be appended to mode to specify the translation mode for newline characters.

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

在文本模式下回车换行符组合将转换为单一的换行输入,并换行字符将转换为输出回车返回换行组合。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).

在二进制(未转换)模式下打开;不进行涉及回车和换行字符的转换。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 中使用文本和二进制模式的详细信息,请参阅 Text and Binary Mode File I/OUnicode Stream I/O in Text and Binary ModesFor more information about how to use 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.

启用关联 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.

将关联 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).

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

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

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

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

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

指定要使用的编码字符集(UTF-8UTF-16LEUNICODE)。Specifies the coded character set to use (UTF-8, UTF-16LE, or UNICODE) for this file. 如果需要 ANSI 编码,请不要指定此字符集。Leave unspecified if you want ANSI encoding.

modefopen 中使用的 _fdopen 字符串的有效字符与 oflag _open _sopen 中使用的参数对应,如下所示:Valid characters for the mode string that is used in fopen and _fdopen correspond to oflag arguments that are used in _open and _sopen, as follows.

模式字符串中的字符Characters in mode string _open/_sopen 的等效 oflagEquivalent oflag value for _open/_sopen
a _O_WRONLY &#124; _O_APPEND(通常为 _O_WRONLY &#124; _O_CREAT &#124; _O_APPEND_O_WRONLY &#124; _O_APPEND (usually _O_WRONLY &#124; _O_CREAT &#124; _O_APPEND)
a+ _O_RDWR &#124; _O_APPEND (通常为 _O_RDWR &#124; _O_APPEND &#124; _O_CREAT_O_RDWR &#124; _O_APPEND (usually _O_RDWR &#124; _O_APPEND &#124; _O_CREAT )
r+ _O_RDWR
w _O_WRONLY (通常为 _O_WRONLY &#124; _O_CREAT &#124; _O_TRUNC_O_WRONLY (usually _O_WRONLY &#124; _O_CREAT &#124; _O_TRUNC)
w+ _O_RDWR (通常为 _O_RDWR &#124; _O_CREAT &#124; _O_TRUNC_O_RDWR (usually _O_RDWR &#124; _O_CREAT &#124; _O_TRUNC)
c None
n None
ccs=UTF-8 _O_UTF8
ccs=UTF-16LE _O_UTF16

如果你使用 rb 模式、不必移植代码、希望读取大文件中的大部分内容或不担心网络性能,你可能还要考虑是否使用内存映射的 Win32 文件方式。If you are using rb mode, do not have to port code, and expect to read most of a large file or are not concerned about network performance, you might also consider whether to use memory mapped Win32 files as an option.


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

_wfopen 是 Microsoft 扩展。_wfopen is a Microsoft extension. 有关兼容性的详细信息,请参阅 CompatibilityFor more information about compatibility, see Compatibility.

c, n, t, S, R, TD mode 选项是 fopen_fdopen 和 should not be used where ANSI portability is desired.The c, n, t, S, R, T, and D mode options are Microsoft extensions for fopen and _fdopen and should not be used where ANSI portability is desired.


以下程序打开两个文件。The following program opens two files. 它使用 fclose 关闭第一个文件,使用 _fcloseall 关闭所有剩余文件。It uses fclose to close the first file and _fcloseall to close all remaining files.

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


以下程序在具有 Unicode 编码的文本模式下创建文件(或在文件存在时覆盖文件)。The following program creates a file (or overwrites one if it exists), in text mode that has Unicode encoding. 然后,它将两个字符串写入文件并关闭文件。It then writes two strings into the file and closes the file. 输出是名为 _wfopen_test.xml 的文件,其中包含输出部分中的数据。The output is a file named _wfopen_test.xml, which contains the data from the output section.

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

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

请参阅See Also

流 I/O Stream I/O
多字节字符序列的解释 Interpretation of Multibyte-Character Sequences
fclose、_fcloseall fclose, _fcloseall
_fdopen、_wfdopen _fdopen, _wfdopen
ferror ferror
_fileno _fileno
freopen、_wfreopen freopen, _wfreopen
_open、_wopen _open, _wopen
_setmode _setmode
_sopen、_wsopen_sopen, _wsopen