If I have a std::ofstream that may or may not have been opened, is it safe to try to close regardless? In otherwords does close() do anything nasty (throw exception, etc) if !is_open(). For example
std::ofstream out;
if (some_condition)
{
out.open(path, std::ios::out);
}
After I'm done with the file, can I just say
out.close();
Or should I first check
if (out.is_open())
out.close();
The only description of std::basic_fstream::close on cppreference is
Closes the associated file.
Effectively calls rdbuf()->close(). If an error occurs during operation, setstate(failbit) is called.
It does exactly what cppreference says it will: the failbit will be set, and you can inspect it with the fail() method. For instance, the following prints "fail\n":
#include <iostream>
#include <fstream>
int main(int argc, char ** argv)
{
std::ofstream out;
out.close();
if (out.fail())
std::cout << "fail" << std::endl;
return 0;
}
In terms of interaction with the operating system, there's nothing there to close, but it's otherwise harmless.
From the C++ standard, §27.9.1.4 [filebuf.members], paragraph 6:
basic_filebuf<charT,traits>* close();
Effects: If is_open() == false, returns a null pointer.…
Yes, you can close() the file always, even the file is not opened.
No matter LINUX or Windows, I always close() without thinking they are opened or not.
From LINUX:
void
close()
{
if (!_M_filebuf.close())
this->setstate(ios_base::failbit);
}
Related
This question already has answers here:
do I need to close a std::fstream? [duplicate]
(3 answers)
Closed 7 years ago.
Below is the code for same case.
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream myfile;
myfile.open ("example.txt");
myfile << "Writing this to a file.\n";
//myfile.close();
return 0;
}
What will be the difference if I uncomment the myfile.close() line?
There is no difference. The file stream's destructor will close the file.
You can also rely on the constructor to open the file instead of calling open(). Your code can be reduced to this:
#include <fstream>
int main()
{
std::ofstream myfile("example.txt");
myfile << "Writing this to a file.\n";
}
To fortify juanchopanza's answer with some reference from the std::fstream documentation
(destructor)
[virtual](implicitly declared)
destructs the basic_fstream and the associated buffer, closes the file
(virtual public member function)
In this case, nothing will happen and code execution time is very less.
However, if your codes runs for long time when you are continuously opening files and not closing, after a certain time, there may be crash in run time.
when you open a file, the operating system creates an entry to represent that file and store the information about that opened file. So if there are 100 files opened in your OS then there will be 100 entries in OS (somewhere in kernel). These entries are represented by integers like (...100, 101, 102....). This entry number is the file descriptor. So it is just an integer number that uniquely represents an opened file in operating system. If your process open 10 files then your Process table will have 10 entries for file descriptors.
Also, this is why you can run out of file descriptors, if you open lots of files at once. Which will prevent *nix systems from running, since they open descriptors to stuff in /proc all the time.
Similar thing should happen in case of all operating system.
Under normal conditions there is no difference.
BUT under exceptional conditions (with slight change) the call to close can cause an expception.
int main()
{
try
{
ofstream myfile;
myfile.exceptions(std::ios::failbit | std::ios::badbit);
myfile.open("example.txt");
myfile << "Writing this to a file.\n";
// If you call close this could potentially cause an exception
myfile.close();
// On the other hand. If you let the destructor call the close()
// method. Then the destructor will catch and discard (eat) the
// exception.
}
catch(...)
{
// If you call close(). There is a potential to get here.
// If you let the destructor call close then the there is
// no chance of getting here.
}
}
I am implementing some file system in C++. Up to now I was using fstream but I realized that it is impossible to open it in exclusive mode. Since there are many threads I want to allow multiple reads, and when opening file in writing mode I want to open the file in exclusive mode?
What is the best way to do it? I think Boost offers some features. And is there any other possibility? I would also like to see simple example. If it is not easy / good to do in C++ I could write in C as well.
I am using Windows.
On many operating systems, it's simply impossible, so C++
doesn't support it. You'll have to write your own streambuf.
If the only platform you're worried about is Windows, you can
possibly use the exclusive mode for opening that it offers.
More likely, however, you would want to use some sort of file
locking, which is more precise, and is available on most, if not
all platforms (but not portably—you'll need LockFileEx
under Windows, fcntl under Unix).
Under Posix, you could also use pthread_rwlock. Butenhof
gives an implementation of this using classical mutex and
condition variables, which are present in C++11, so you could
actually implement a portable version (provided all of the
readers and writers are in the same process—the Posix
requests will work across process boundaries, but this is not
true for the C++ threading primitives).
if your app only works on Windows, the Win32 API function CreateFile() is your choice.
For example:
HANDLE hFile = ::CreateFileW(lpszFileFullPathName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
If you are open to using boost, then I would suggest you use the file_lock class. This means you want to keep the filename of the files you open/close because fstream does not do so for you.
They have two modes lock() that you can use for writing (i.e. only one such lock at a time, the sharable lock prevents this lock too) and lock_sharable() that you can use for reading (i.e. any number of threads can obtain such a lock).
Note that you will find it eventually complicated to manage both, read and write, in this way. That is, if there is always someone to read, the sharable lock may never get released. In that case, the exclusive lock will never be given a chance to take....
// add the lock in your class
#include <boost/interprocess/sync/file_lock.hpp>
class my_files
{
...
private:
...
boost::file_lock m_lock;
};
Now when you want to access a file, you can lock it one way or the other. If the thread is in charge of when they do that, you could add functions for the user to have access to the lock. If your implementation of the read and write functions in my_files are in charge, you want to get a stack based object that locks and unlocks for you (RAII):
class safe_exclusive_lock
{
public:
safe_exclusive_lock(file_lock & lock)
: m_lock_ref(lock)
{
m_lock_ref.lock();
}
~safe_exclusive_lock()
{
m_lock_ref.unlock();
}
private:
file_lock & m_lock_ref;
};
Now you can safely lock the file (i.e. you lock, do things that may throw, you always unlock before exiting your current {}-block):
ssize_t my_files::read(char *buf, size_t len)
{
safe_exclusive_lock guard(m_lock);
...your read code here...
return len;
} // <- here we get the unlock()
ssize_t my_files::write(char const *buf, size_t len)
{
safe_exclusive_lock guard(m_lock);
...your write code here...
return len;
} // <- here we get the unlock()
The file_lock uses a file, so you will want to have the fstream file already created whenever the file_lock is created. If the fstream file may not be created in your constructor, you probably will want to transform the m_lock variable in a unique pointer:
private:
std::unique_ptr<file_lock> m_lock;
And when you reference it, you now need an asterisk:
safe_exclusive_lock guard(*m_lock);
Note that for safety, you should check whether the pointer is indeed allocated, if not defined, it means the file is not open yet so I would suggest you throw:
if(m_lock)
{
safe_exclusive_lock guard(*m_lock);
...do work here...
}
else
{
throw file_not_open();
}
// here the lock was released so you cannot touch the file anymore
In the open, you create the lock:
bool open(std::string const & filename)
{
m_stream.open(...);
...make sure it worked...
m_lock.reset(new file_lock(filename));
// TODO: you may want a try/catch around the m_lock and
// close the m_stream if it fails or use a local
// variable and swap() on success...
return true;
}
And do not forget to release the lock object in your close:
void close()
{
m_lock.reset();
}
Well you can manually prevent yourself from opening a file if it has been opened in write mode already. Just keep track internally of which files you've opened in write mode.
Perhaps you could hash the filename and store it in a table upon open with write access. This would allow fast lookup to see if a file has been opened or not.
You could rename the file, update it under the new name, and rename it back. I've done it, but it's a little heavy.
Since C++17 there are two options:
In C++23 by using the openmode std::ios::noreplace.
In C++17 by using the std::fopen mode x (exclusive).
Note: The x mode was added to c in C11.
C++23 and later:
#include <cerrno>
#include <cstring>
#include <fstream>
#include <iostream>
int main() {
std::ofstream ofs("the_file", std::ios::noreplace);
if (ofs) {
std::cout << "success\n";
} else {
std::cerr << "Error: " << std::strerror(errno) << '\n';
}
}
Demo
C++17 and later:
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <memory>
struct FILE_closer {
void operator()(std::FILE* fp) const { std::fclose(fp); }
};
// you may want overloads for `std::filesystem::path`, `std::string` etc too:
std::ofstream open_exclusively(const char* filename) {
bool excl = [filename] {
std::unique_ptr<std::FILE, FILE_closer> fp(std::fopen(filename, "wx"));
return !!fp;
}();
auto saveerr = errno;
std::ofstream stream;
if (excl) {
stream.open(filename);
} else {
stream.setstate(std::ios::failbit);
errno = saveerr;
}
return stream;
}
int main() {
std::ofstream ofs = open_exclusively("the_file");
if (ofs) {
std::cout << "success\n";
} else {
std::cout << "Error: " << std::strerror(errno) << '\n';
}
}
Demo
If I run the following code, no file is created at all:
std::ofstream outputFile(strOutputLocation.c_str(), std::ios::binary);
outputFile.write((const char*)lpResLock, dwSizeRes);
outputFile.close();
However, if I add a flush() before the close, it works:
std::ofstream outputFile(strOutputLocation.c_str(), std::ios::binary);
outputFile.write((const char*)lpResLock, dwSizeRes);
outputFile.flush();
outputFile.close();
Does the standard library actually require this, or is it a bug in the Visual C++ CRT?
It's a bug. Reading §27.8.1.10/4, abridged:
void close();
Effects: Calls rdbuf()->close()...
What does rdbuf()->close() do? According to §27.8.1.3/6, abridged, emphasis mine:
basic_filebuf<charT,traits>* close();
If is_open() == false, returns a null pointer. If a put area exists, calls overflow(EOF) to flush characters. ...
That is, it's suppose to flush. (Indeed, the call to flush() ultimately does the same thing.)
Note the call to close() itself isn't needed, as the destructor of basic_ofstream will call close().
Are you checking the file before you exit from the program? OS will buffer all IO, so may not see any data(unless you flush) in the file before you exit.
I have ifstream and an ofstream that in runtime might be opened or not (depends on what the user enters in command line. i declare the variables anyway, and i have a method that opens the stream if needed.
my problem is at the end of the program i don't know if i need to close them or not.
Is there anyway in c++ to know if a stream was opened? Like in Java you can give a stream the null value and then ask if its null (it means that it was never opened)..
Is it ok to close a stream that was never opened?
this is the code:
int main(int argc, char* argv[]) {
static std::ifstream ifs;
static std::ofstream ofs;
//might or might not open the streams:
OpenStreams(ifs,ofs,argc-1,argv);
........
//here i would like to close the streams at the end of the program
//or not (if they were not opened
return 0;
}
Thanks!
I don't really know, nor care to look. Just leave it to the destructors, the standard file streams will close the files during destruction if needed.
EDIT: On lifetimes of objects and guaranteed destruction...
To follow up the second comment to Ben Voigt that I wrote, this is a small test on object lifetimes:
#include <cstdlib>
#include <iostream>
#include <string>
struct test {
std::string name;
test( std::string const & name ) : name(name) {
std::cout << "test " << name << std::endl;
}
~test() { std::cout << "~test " << name << std::endl; }
};
void foo( bool exit ) {
test t1( "1" );
static test t2( "2" );
test t3( "3" );
if ( exit ) {
std::exit(1);
}
}
int main()
{
foo(false);
std::cout << std::endl;
foo(true);
}
And the result of the execution:
test 1
test 2
test 3
~test 3
~test 1
test 1
test 3
~test 2
It can be seen that during the first execution the construction of the objects in foo occurs in the same order as the code., but when the function exits only the objects with auto storage get destroyed, with the object with static storage outliving the function execution.
In the second call to foo, the auto objects get recreated, while the static object doesn't, as expected, since it was created in a previous call. Because foo calls exit() in the second call, the auto objects in foo don't get destructed. On the other hand, the static object is correctly destructed.
Why not just test this using is_open() before you issue the close()?
No close call needed - the streams close itself when they are open when they are destroyed. Also, the static there looks suspicious. main is called only once, so it doesn't have any effect here (apart from pedantic standardese differences that don't matter here, i think.... Definitely not in the case shown).
That said, you can just call close if a stream is not opened - close will return a null pointer if it wasn't open. (I was looking at the spec for basic_filebuf<>::close - the file streams's close returns void).
File-streams can also handle non-open streams: If the stream wasn't open, it sets the failbit. You can check for that using fail() (which tests whehter the failbit or badbit is set). But there is is_open anyway to test whether the stream is open, but you don't need it for the above reasons.
Just don't make the variables static, that way they automatically close when main() returns.
You can use the is_open method to test if a stream has been opened, then close it.
Why not set a flag before opening a stream. Check the flag again if you need to close the stream object if any.
Better would be to pass that open stream object to the flag while opening a stream & use it to close the stream. If the flag has not been initialized or is null don't close.
Do I need to manually call close() when I use a std::ifstream?
For example, in the code:
std::string readContentsOfFile(std::string fileName) {
std::ifstream file(fileName.c_str());
if (file.good()) {
std::stringstream buffer;
buffer << file.rdbuf();
file.close();
return buffer.str();
}
throw std::runtime_exception("file not found");
}
Do I need to call file.close() manually? Shouldn't ifstream make use of RAII for closing files?
NO
This is what RAII is for, let the destructor do its job. There is no harm in closing it manually, but it's not the C++ way, it's programming in C with classes.
If you want to close the file before the end of a function you can always use a nested scope.
In the standard (27.8.1.5 Class template basic_ifstream), ifstream is to be implemented with a basic_filebuf member holding the actual file handle. It is held as a member so that when an ifstream object destructs, it also calls the destructor on basic_filebuf. And from the standard (27.8.1.2), that destructor closes the file:
virtual ˜basic_filebuf();
Effects: Destroys an object of class basic_filebuf<charT,traits>. Calls close().
Do you need to close the file?
NO
Should you close the file?
Depends.
Do you care about the possible error conditions that could occur if the file fails to close correctly? Remember that close calls setstate(failbit) if it fails. The destructor will call close() for you automatically because of RAII but will not leave you a way of testing the fail bit as the object no longer exists.
You can allow the destructor to do it's job. But just like any RAII object there may be times that calling close manually can make a difference. For example:
#include <fstream>
using std::ofstream;
int main() {
ofstream ofs("hello.txt");
ofs << "Hello world\n";
return 0;
}
writes file contents. But:
#include <stdlib.h>
#include <fstream>
using std::ofstream;
int main() {
ofstream ofs("hello.txt");
ofs << "Hello world\n";
exit(0);
}
doesn't. These are rare cases where a process suddenly exits. A crashing process could do similar.
No, this is done automatically by the ifstream destructor. The only reason you should call it manually, is because the fstream instance has a big scope, for example if it is a member variable of a long living class instance.