Ch11.14: Win32 File APIs
Overview
On Windows, user-mode applications talk to the kernel through kernel32.dll.
The two entry points for opening files are:
-
CreateFileW— the wide-character (UTF-16) variant, used on every modern Windows release (NT, 2000, XP, 7, 10, 11). -
CreateFileA— the ANSI variant, still encountered on the Windows 9x family (95, 98, ME).
fast_io hides this difference behind two types, mirroring the POSIX layer:
-
::fast_io::win32_file— an RAII owning wrapper that callsCreateFileW(orCreateFileAon 9x) in its constructor andCloseHandlein its destructor. -
::fast_io::win32_io_observer— a non-owning view over an existingHANDLE. Trivially copyable, no destructor.
Choosing Between ANSI and Wide: win32_api_family
The Win32 layer exposes a traits type called
::fast_io::win32_api_family. It selects which variant of the API should
be used on a given Windows target:
-
On the NT family (the default for any supported compiler today), the family picks
CreateFileWand the wide-character overloads. -
On the 9x family, the family picks
CreateFileAand the ANSI overloads.
In practice you almost never need to touch win32_api_family directly:
win32_file consults it automatically when you pass a filename.
Opening a File with win32_file
#include <fast_io.h>
#include <fast_io_device.h>
int main()
{
using namespace ::fast_io::iomnp;
// The constructor picks CreateFileW or CreateFileA through
// ::fast_io::win32_api_family.
::fast_io::win32_file wf(u8"hello_win32.txt", ::fast_io::open_mode::out);
println(wf, u8"Hello from win32_file!");
::std::size_t const n{42zu};
println(wf, u8"The answer is: ", n);
// CloseHandle is invoked automatically when `wf` goes out of scope.
}
Wrapping an Existing HANDLE
Just like posix_io_observer, you can build a non-owning view over a
HANDLE you obtained elsewhere:
#include <fast_io.h>
#include <fast_io_device.h>
void write_via_handle(void* h)
{
using namespace ::fast_io::iomnp;
// Non-owning: does NOT call CloseHandle on destruction.
::fast_io::win32_io_observer observer{
static_cast<::fast_io::win32_io_observer::native_handle_type>(h)};
println(observer, u8"Written through a win32_io_observer\n");
}
int main()
{
::fast_io::win32_file wf(u8"legacy_handle.txt", ::fast_io::open_mode::out);
write_via_handle(wf.native_handle());
}
Reading and Open-at
Reading uses scan. Opening relative to a directory handle uses
NtCreateFile under the hood because the Win32 API itself has no
*at equivalent:
#include <fast_io.h>
#include <fast_io_device.h>
int main()
{
using namespace ::fast_io::iomnp;
::fast_io::win32_file inpf(u8"input.txt", ::fast_io::open_mode::in);
::std::size_t value{};
::fast_io::scan(inpf, value);
::fast_io::win32_file outpf(u8"output.txt", ::fast_io::open_mode::out);
println(outpf, u8"Read the value: ", value);
}
Summary
-
::fast_io::win32_filewraps the Win32CreateFileW/CreateFileAentry point with RAII. -
::fast_io::win32_io_observeris a non-owning view over an existingHANDLE. -
::fast_io::win32_api_familyselects between the ANSI and Wide variants based on the target Windows family. You normally do not need to interact with it directly. -
All standard
fast_ioalgorithms —print,println,scan— work on these types.