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 any 任意 EINVAL 未更改
any NULL 任意 EINVAL 未更改
any 任意 NULL EINVAL 未更改

备注

fopen_s_wfopen_s 函数无法打开用于共享的文件。 如果需要共享文件,请将 _fsopen_wfsopen 与适当的共享模式常量配合使用(例如,将 _SH_DENYNO 用于读/写共享)。

fopen_s 函数打开由 filename 指定的文件。 _wfopen_sfopen_s 的宽字符版本,_wfopen_s 的参数是宽字符字符串。 除此以外,_wfopen_sfopen_s 的行为完全相同。

fopen_s 接受执行时文件系统上有效的路径;fopen_s 接受 UNC 路径以及包含所映射网络驱动器的路径,前提是执行代码的系统在执行时能够访问共享或映射的网络驱动器。 为 fopen_s 构造路径时,请勿做出有关驱动器、路径或执行环境中网络共享的可用性假设。 可使用斜杠 (/) 或反斜杠 (\) 作为路径中的目录分隔符。

这些函数验证其参数。 如果 pFilefilenamemode 为 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");

ccs 标志的允许值为 UNICODEUTF-8UTF-16LE。 如果未为 ccs 指定值,则 fopen_s 将使用 ANSI 编码。

如果文件已存在并已打开以进行读取或追加,则字节顺序标记 (BOM)(如果文件中存在)将确定编码。 BOM 编码优先于 ccs 标志指定的编码。 仅在不存在 BOM 或如果文件是新文件时,才使用 ccs 编码。

注意

BOM 检测仅适用于在 Unicode 模式下打开的文件;即,通过传递 ccs 标志打开的文件。

下表汇总了提供给 fopen_s 的各种 ccs 标志值的模式以及文件中的 BOM 的模式。

基于 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 Access
"r" 打开以便读取。 如果文件不存在或找不到,fopen_s 调用将失败。
"w" 打开用于写入的空文件。 如果给定文件存在,则其内容会被销毁。
"a" 在文件末尾打开以进行写入(追加),在新数据写入到文件之前不移除文件末尾 (EOF) 标记。 如果文件不存在,则创建文件。
"r+" 打开以便读取和写入。 文件必须存在。
"w+" 打开用于读取和写入的空文件。 如果文件存在,则其内容会被销毁。
"a+" 打开以进行读取和追加。 追加操作包括在新数据写入文件之前移除 EOF 标记。 写入完成后,EOF 标记不会还原。 如果文件不存在,则创建文件。

通过使用 "a""a+" 访问类型打开文件时,所有写入操作均将在文件末尾进行。 使用 fseekrewind 可重新定位文件指针,但在执行任何写入操作前,文件指针将始终被移回文件末尾,以确保不会覆盖现有数据。

在 EOF 标记追加到文件之前,"a" 模式会将其删除。 追加后,MS-DOS TYPE 命令仅显示原始 EOF 标记之前的数据,不显示追加到文件的任何数据。 在 EOF 标记追加到文件之前,"a+" 模式会将其删除。 在追加后,MS-DOS TYPE 命令显示文件中的所有数据。 需使用 "a+" 模式才能附加到通过 CTRL+Z EOF 标记终止的流文件。

当指定 "r+""w+""a+" 访问类型时,允许读取和写入。 (文件据说已经可以进行“更新”。)但是,当你从读取切换到写入时,输入操作必定会遇到 EOF 标记。 如果没有 EOF 标记,必须使用对文件定位函数的干预调用。 文件定位函数是 fsetposfseekrewind。 从写入切换到读取时,必须使用对 fflush 或文件定位函数的干预调用。

从 C11 开始,可以将 "x" 追加到 "w",或追加 "w+" 以使函数在该文件存在时失败,而不是覆盖该文件。

除了上述值之外,可以在 mode 中包含以下字符以指定换行符的转换模式:

mode 修饰符 转换模式
t 在文本(转换)模式下打开。 输入时,回车换行 (CR-LF) 组合将转换为单一的换行 (LF);输出时,LF 字符将转换为 CR-LF 组合。 CTRL+Z 将在输入时解释为文件尾字符。
b 在二进制(未转换)模式下打开;禁止涉及回车和换行字符的转换。

在文本(已转换)模式中,CTRL+Z 将在输入时解释为文件结尾字符。 在打开使用 "a+" 进行读取/写入的文件中,fopen_s 将检查文件末尾的 CTRL+Z 并在可能的情况下将其删除。 将其删除是因为使用 fseekftell 在以 CTRL+Z 结尾的文件中移动时,可能导致 fseek 在文件末尾附近错误运行。

另外,在文本模式下,输入时,回车/换行 (CRLF) 组合将转换为单一的换行 (LF) 字符;输出时,LF 字符将转换为 CRLF 组合。 当 Unicode 流 I/O 函数在文本模式(默认设置)下运行时,源或目标流将假定为一系列多字节字符。 Unicode 流输入函数将多字节字符转换为宽字符(就像调用 mbtowc 函数一样)。 出于同一原因,Unicode 流输出函数将宽字符转换为多字节字符(就像调用 wctomb 函数一样)。

如果 tbmode 中未给出,则默认转换模式由全局变量 _fmode 定义。 如果 tb 是该参数的前缀,则函数将失败并返回 NULL

有关在 Unicode 和多字节流 I/O 中使用文本和二进制模式的详细信息,请参阅文本和二进制模式文件 I/O文本和二进制模式下的 Unicode 流 I/O

mode 修饰符 行为
c 启用关联 filename 的提交标志,以便在调用 fflush_flushall 时将文件缓冲区的内容直接写入磁盘。
n 将关联的 filename 的提交标志重置为“no-commit”。此标志为默认值。 如果将程序显式链接到 COMMODE.OBJ,它还将重写全局提交标志。 除非将程序显式链接到 COMMODE.OBJ,否则全局提交标志默认为 "no-commit"(请参阅链接选项)。
N 指定文件不由子进程继承。
S 指定缓存针对(但不限于)从磁盘的顺序访问进行优化。
R 指定缓存针对(但不限于)从磁盘的随机访问进行优化。
T 指定一个文件,除非内存压力需要它,否则不会写入磁盘。
D 指定在关闭最后一个指向该文件的指针时删除的临时文件。
ccs=UNICODE 指定 UNICODE 作为要用于此文件的编码字符集。 如果需要 ANSI 编码,请不要指定此字符集。
ccs=UTF-8 指定 UTF-8 作为要用于此文件的编码字符集。 如果需要 ANSI 编码,请不要指定此字符集。
ccs=UTF-16LE 指定 UTF-16LE 作为要用于此文件的编码字符集。 如果需要 ANSI 编码,请不要指定此字符集。

fopen_s_fdopen 中使用的 mode 字符串的有效字符对应于在 _open_sopen 中使用的 oflag 参数,如下所示。

字符串中的 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

c、、nRStTmode D选项Microsoft扩展fopen_s_wfopen_s,并且不应在需要 ANSI 可移植性时使用。

如果使用 rb 模式,并且无需移植代码、预计将读取大量文件或者不关心网络性能,则内存映射的 Win32 文件可能也是一个选项。

关于 TD

  • 只要内存压力不需要,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