Редагувати

Поділитися через


fopen, _wfopen

Opens a file. More-secure versions of these functions that perform more parameter validation and return error codes are available; see fopen_s, _wfopen_s.

Syntax

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

Parameters

filename
File name.

mode
Kind of access that's enabled.

Return value

Each of these functions returns a pointer to the open file. A null pointer value indicates an error. If filename or mode is NULL or an empty string, these functions trigger the invalid parameter handler, which is described in Parameter validation. If execution is allowed to continue, these functions return NULL and set errno to EINVAL.

For more information, see errno, _doserrno, _sys_errlist, and _sys_nerr.

Remarks

The fopen function opens the file specified by filename. By default, a narrow filename string is interpreted using the ANSI codepage (CP_ACP). In Windows Desktop applications, it can be changed to the OEM codepage (CP_OEMCP) by using the SetFileApisToOEM function. You can use the AreFileApisANSI function to determine whether filename is interpreted using the ANSI or the system default OEM codepage. _wfopen is a wide-character version of fopen; the _wfopen arguments are wide-character strings. Otherwise, _wfopen and fopen behave identically. Just using _wfopen doesn't affect the coded character set that's used in the file stream.

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. When you construct paths for fopen, make sure that drives, paths, or network shares are available in the execution environment. You can use either forward slashes (/) or backslashes (\) as the directory separators in a path.

Always check the return value to see whether the pointer is NULL before you perform any other operations on the file. If an error occurs, the global variable errno is set, and may be used to obtain specific error information. For more information, see errno, _doserrno, _sys_errlist, and _sys_nerr.

By default, this function's global state is scoped to the application. To change it, see Global state in the CRT.

Unicode support

fopen supports Unicode file streams. To open a Unicode file, pass a ccs=encoding flag that specifies the desired encoding to fopen, as follows.

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

Allowed values for ccs encoding are UNICODE, UTF-8, and UTF-16LE.

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. Functions that write to a file opened in Unicode mode expect buffers that contain UTF-16 data stored as type wchar_t. If the file is encoded as UTF-8, then UTF-16 data is translated into UTF-8 when it's written. The file's UTF-8-encoded content is translated into UTF-16 when it's read. An attempt to read or write an odd number of bytes in Unicode mode causes a parameter validation error. 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're responsible for any required encoding translation.

If the file already exists and is opened for reading or appending, then any byte order mark (BOM) in the file determines the encoding. The BOM encoding takes precedence over the encoding specified by the ccs flag. The ccs encoding is only used when no BOM is present or the file is a new file.

Note

BOM detection only applies to files that are opened in Unicode mode (that is, by passing the ccs flag).

The following table summarizes the modes that are used for various ccs flags given to fopen and Byte Order Marks in the file.

Encodings used based on ccs flag and BOM

ccs flag No BOM (or new file) 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

Files opened for writing in Unicode mode have a BOM written to them automatically.

If mode is a, ccs=encoding for some encoding value, fopen first tries to open the file by using both read and write access. If this action succeeds, the function reads the BOM to determine the encoding for the file. If it fails, the function uses the default encoding for the file. In either case, fopen reopens the file using write-only access. (This behavior applies to "a" mode only, not to "a+" mode.)

Generic-text routine mappings

TCHAR.H routine _UNICODE and _MBCS not defined _MBCS defined _UNICODE defined
_tfopen fopen fopen _wfopen

The character string mode specifies the kind of access that is requested for the file, as follows.

mode Access
"r" Opens for reading. If the file doesn't exist or can't be found, the fopen call fails.
"w" Opens an empty file for writing. If the given file exists, its contents are destroyed.
"a" 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 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. The appending operation includes the removal of the EOF marker before new data is written to the file. The EOF marker isn't restored after writing is completed. Creates the file if it doesn't exist.

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. 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 can't be overwritten.

The "a" mode doesn't remove the EOF marker before it appends to the file. 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. Before it appends to the file, the "a+" mode does remove the EOF marker. After appending, the MS-DOS TYPE command shows all data in the file. The "a+" mode is required for appending to a stream file that is terminated with the CTRL+Z EOF marker.

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"). However, when you switch from reading to writing, the input operation must encounter an EOF marker. If there's no EOF, you must use an intervening call to a file positioning function. The file positioning functions are fsetpos, fseek, and rewind. When you switch from writing to reading, you must use an intervening call to either fflush or to a file positioning function.

In addition to the earlier values, the following characters can be appended to mode to specify the translation mode for newline characters.

mode modifier Translation mode
t Open in text (translated) mode. Carriage return-line feed (CR-LF) combinations are translated into single line feeds (LF) on input and LF characters are translated to CR-LF combinations on output. Also, CTRL+Z is interpreted as an end-of-file character on input.
b Open in binary (untranslated) mode; translations involving carriage-return and line feed characters are suppressed.

In text mode, CTRL+Z is interpreted as an EOF character on input. 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's possible. It's removed 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-line feed (CRLF) combinations are translated into single line feed (LF) characters on input, and LF characters are translated to CRLF combinations on output. 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. Therefore, the Unicode stream-input functions convert multibyte characters to wide characters (as if by a call to the mbtowc function). For the same reason, the Unicode stream-output functions convert wide characters to multibyte characters (as if by a call to the wctomb function).

If t or b isn't given in mode, the default translation mode is defined by the global variable _fmode. If t or b is prefixed to the argument, the function fails and returns NULL.

For 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.

The following options can be appended to mode to specify more behaviors.

mode modifier Behavior
x Forces the function to fail if filename already exists. Can only be used with the "w" or "w+" specifiers.
c 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 Reset the commit flag for the associated filename to "no-commit." This flag is the default. It also overrides the global commit flag if you link your program with COMMODE.OBJ. 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 isn't 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 that isn't written to disk unless memory pressure requires it.
D Specifies a temporary file that's deleted when the last file pointer to it is closed.
ccs=encoding Specifies the encoded character set to use (one of UTF-8, UTF-16LE, or UNICODE) for this file. Leave unspecified if you want ANSI encoding. This flag is separated from flags that precede it by a comma (,). For example: FILE *f = fopen("newfile.txt", "rt+, ccs=UTF-8");

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 Equivalent oflag value for _open/_sopen
a _O_WRONLY | _O_APPEND (usually _O_WRONLY | _O_CREAT | _O_APPEND)
a+ _O_RDWR | _O_APPEND (usually _O_RDWR | _O_APPEND | _O_CREAT )
r _O_RDONLY
r+ _O_RDWR
w _O_WRONLY (usually _O_WRONLY | _O_CREAT | _O_TRUNC)
w+ _O_RDWR (usually _O_RDWR | _O_CREAT | _O_TRUNC)
b _O_BINARY
t _O_TEXT (translated)
x _O_EXCL
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

If you're using rb mode, you don't have to port your code, and if you expect to read most of a large file or aren't concerned about network performance, you might also consider whether to use memory mapped Win32 files as an option.

Regarding T and D:

  • T avoids writing the file to disk as long as memory pressure doesn't require it. For more information, see FILE_ATTRIBUTE_TEMPORARY in File attribute constants, and also this blog post It's only temporary.
  • D specifies a regular file that is written to disk. The difference is that it's automatically deleted when it's closed. You can combine TD to get both semantics.

The c, n, R, S, t, T, and D mode options are Microsoft extensions for fopen and _wfopen and shouldn't be used when you want ANSI portability.

Requirements

Function Required header
fopen <stdio.h>
_wfopen <stdio.h> or <wchar.h>

_wfopen is a Microsoft extension. For more information about compatibility, see Compatibility.

The c, n, t, S, R, T, and D mode options are Microsoft extensions for fopen and _fdopen and shouldn't be used where ANSI portability is desired.

Example 1

The following program opens two files. 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" );
   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

Example 2

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. 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");
        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;
}

See also

Stream I/O
Interpretation of multibyte-character sequences
fclose, _fcloseall
_fdopen, _wfdopen
ferror
_fileno
freopen, _wfreopen
_open, _wopen
_setmode
_sopen, _wsopen