Can I use CreateFile, but force the handle into a std::ofstream?
It is possible to attach a C++ std::ofstream
to a Windows file handle. The following code works in VS2008:
HANDLE file_handle = CreateFile(
file_name, GENERIC_WRITE,
0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (file_handle != INVALID_HANDLE_VALUE) {
int file_descriptor = _open_osfhandle((intptr_t)file_handle, 0);
if (file_descriptor != -1) {
FILE* file = _fdopen(file_descriptor, "w");
if (file != NULL) {
std::ofstream stream(file);
stream << "Hello World\n";
// Closes stream, file, file_descriptor, and file_handle.
stream.close();
file = NULL;
file_descriptor = -1;
file_handle = INVALID_HANDLE_VALUE;
}
}
This works with FILE_FLAG_DELETE_ON_CLOSE
, but FILE_FLAG_WRITE_THROUGH
may not have the desired effect, as data will be buffered by the std::ofstream
object, and not be written directly to disk. Any data in the buffer will be flushed to the OS when stream.close()
is called, however.
Getting a HANDLE from a std::ofstream
The C++ standard does not provide any means for specifying or retrieving the raw file descriptors of an ofstream
, so I don't believe this is possible. What is possible, though, would be to build a custom streambuf
class that implements stream buffering to and from a HANDLE
, then to define a custom ostream
type that uses that buffer. I'm not sure if that's really what you're looking for, but it is a viable option.
Force encoding when writing txt file with ofstream
You can call std::ios::imbue
on your ofstream
object to modify the locale. This won't affect the global locale.
std::ofstream os("output.txt");
std::locale mylocale("");
os.imbue(mylocale);
os << 1.5f << std::endl;
os.close();
Pay attention to the argument of std::locale
constructor, it is implementation dependant. For example, the German locale could be :
std::locale mylocale("de_DE");
or
std::locale mylocale("German");
How to share file delete privilege when I opening a file by ifstream
Visual Studio's version of std::ifstream
has a non-standard constructor and a non-standard open()
overload that both have an extra optional _Prot
parameter for specifying "file protection/sharing flags" (see _fsopen()
for the list of available flags). However, delete
sharing is not one of supported flags.
There is an alternative, though. Visual Studio's version of both std::ifstream
and std::ofstream
have non-standard constructors that accept a FILE*
for the file access. You can wrap a HANDLE
from CreateFile()
into a FILE*
using Microsoft's _open_osfhandle()
and _fdopen()
functions, for example (error handling removed for brevity):
Can I use CreateFile, but force the handle into a std::ofstream?
HANDLE file_handle = CreateFile(...,FILE_SHARE_DELETE,...);
int file_descriptor = _open_osfhandle((intptr_t)file_handle, _O_RDONLY);
FILE* file = _fdopen(file_descriptor, "r");
std::ifstream stream(file);
...
// Closes stream, file, file_descriptor, and file_handle.
stream.close();
If you need something more portable to non-Microsoft compilers, you will likely have to resort to writing a custom std::basic_streambuf
class (or maybe derived from std::filebuf
) to wrap your HANDLE
, and then pass an object of that class to the std::basic_istream
constructor directly.
Why I am unable to open a file RW with CreateFile Win32 API but can remove it with std::remove?
Windows has specific DELETE
permissions (not relevant for FAT filesystems, but natively implemented on NTFS). These are independent from WRITE
permissions. Permissions might exist on the file itself or be inherited from the parent (i.e. directory).
On Unix and Linux, things are slightly different; files deletes are handled there via write permissions on the parent directory.
Is there a way to write into a file while another process is reading?
You're on Windows, so the C++ way is
CreateFile(.... FILE_SHARE_READ | FILE_SHARE_WRITE, ....)
It returns a Win32 HANDLE
, which is not the easiest thing to use in C++ (there are no convenience functions for formatted I/O). But you can turn it into a FILE*
or fstream
.
See this question:
- Can I use CreateFile, but force the handle into a std::ofstream?
Or, you can use the shflag
parameter of _fsopen()
or the _Prot
parameter of an fstream
constructor:
The argument shflag is a constant expression consisting of one of the
following manifest constants, defined in Share.h.Term Definition
_SH_COMPAT
Sets Compatibility mode for 16-bit applications.
_SH_DENYNO
Permits read and write access.
_SH_DENYRD
Denies read access to the file.
_SH_DENYRW
Denies read and write access to the file.
_SH_DENYWR
Denies write access to the file.
MSDN has the documentation and examples
Related Topics
How Does One Securely Clear Std::String
Using Class Name in a Class Template Without Template Parameters
Difference Between C++03 Throw() Specifier C++11 Noexcept
Why Is It Undefined Behavior to Delete[] an Array of Derived Objects via a Base Pointer
Know If .Lib Is Static or Import
Linux Allocator Does Not Release Small Chunks of Memory
C++ Return Value Without Return Statement
Can a Pointer to Base Point to an Array of Derived Objects
When Is It Necessary to Use the Flag -Stdlib=Libstdc++
Declare Template Friend Function of Template Class
Serial Comm Using Writefile/Readfile
Cpp - Valgrind - Invalid Read of Size 8
Why Are Memcpy() and Memmove() Faster Than Pointer Increments
Evaluate a String with a Switch in C++
How to Convert a Reverse Iterator to a Forward Iterator
"String Could Not Resolved" Error in Eclipse for C++ (Eclipse Can't Resolve Standard Library)