Calling ofstream.close doesn't release the file - c++

After executing code like this:
{
ofstream ofs("file.txt", ios::app);
ofs << "Output" << endl;
ofs.close();
Sleep(100); //just in case
bool opened = ofs.is_open(); //always false
} //ofs out of scope
I would expect file.txt to be completely free, but if I open it with notepad I cant edit the file because it's owned by process until my program exits. How do I make the file accessible?

Related

std::getline with std::fstream

I am using std::fstream to read and write to the same file. I can see the write happening but not the read.
After searching the web, I got to know that I can not set in and app mode together. So, got rid of that and made it very simple of not passing any arguments.
I am very interested to know the reason why read is not happening.
Also, how do people read and write to the same file using same fstream?
My code:
#include<iostream>
#include<fstream>
int main() {
std::fstream* fs = new std::fstream("xx.txt");
*fs << "Hello" << std::endl;
(*fs).close(); // ?
std::string line;
while(std::getline(*fs, line)) {
std::cout << line << std::endl;
}
}
With this code, I can xx.txt contain "Hello" as its content but it does not go inside the while loop at all stating that reading failed.
How can I overcome this?
You forgot to reopen the stream. Actually you can't open a stream in both directions (at the same time).
So the steps are:
Open the stream for writing
Write data
Close the stream
Reopen the stream for reading
Read data
Close it (optional)
Your sample can be rewritten as:
#include <fstream>
#include <iostream>
int main()
{
const std::string file_path("xx.txt");
std::fstream fs(file_path, std::fstream::app);
if(fs) // Check if the opening has not failed
{
fs << "Hello" << std::endl;
fs.close();
}
fs.open(file_path, std::fstream::in);
if(fs) // Check if the opening has not failed
{
std::string line;
while(std::getline(fs, line))
{
std::cout << line << std::endl;
}
fs.close();
}
return 0;
}
Note that it is a good idea to check if the stream is successfully open before trying to use it.
I will try to explain the issue.
Statement std::fstream* fs = new std::fstream("xx.txt"); will open file if it exists in default mode "in|out" .
If the file does not exist then the call to open from inside of constructor std::fstream will fail. And this can be checked by checking failbit using function fail(). So you will explicitly need to call 'open' to use the fstream object for data input. Note: the new file will not be created unless you call 'close'.
You can test this by actually trying to open an existing file or new file you can see the difference.
So alternatively what you should do is always call 'open' which will work in both cases (if file exists or not).
#include<iostream>
#include<fstream>
int main() {
//std::fstream fs("xx.txt");
//std::cout << fs.fail() << std::endl; // print if file open failed or passed
std::fstream fs;
fs.open("xx.txt", std::fstream::in | std::fstream::out | std::fstream::app);
std::cout << fs.fail() << std::endl;
fs << "Hello" << std::endl;
if (fs.is_open())
{
std::cout << "Operation successfully performed\n";
fs.close();
}
else
{
std::cout << "Error opening file";
}
For reading the content of the file you will first need to close the file. And then reopen and read. As I understand once you start using the object fs for insertion you cannot read from it unless you explicitly close it and reopen.
fs.open("xx.txt", std::fstream::in | std::fstream::out);
std::string line;
while(std::getline(fs, line)) {
std::cout << line << std::endl;
}
std::cout << "end" << std::endl;
fs.close();
}

Qt QFile return non existent but still opens and writes to file

I have this file which is located in my C drive, I know it exists. When I access it with QFile.exists() it returns false, however it still opens the file and writes to it, I just cant read it. I've been working on this for a while and cannot find a solution, any suggestions are appreciated.
QFile tmpfile("C:/file.txt");
QString tmpcontent;
if(!QFile::exists("C:/file.txt"))
qDebug() << "File not found"; // This is outputted
if (tmpfile.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
QTextStream stream(&tmpfile);
stream << "test"; //this is written
tmpcontent = tmpfile.readAll(); // this returns nothing
}
If file is not exist it will be created by open because you do it in write mode.
readAll function return all remaining data from device, since you just write something you are currently at the end of a file, and there is no data, try to seek( 0 ) to return to the beginnig of a file and then use readAll.
qDebug() << "File exists: " << QFile::exists("text.txt");
QFile test( "text.txt" );
if ( test.open( QIODevice::ReadWrite | QIODevice::Truncate ) ){
QTextStream str( &test );
str << "Test string";
qDebug() << str.readAll();
str.seek( 0 );
qDebug() << str.readAll();
test.close();
}else{
qDebug() << "Fail to open file";
}
As I can see from your code you need that file as a temporary, in such case I suggest to use QTemporaryFile, it will be created in temp directory (I belive there will be no problem with permissions), with unique name and will be auto deleted in object dtor.

ofstream failing to create file when program runs with sudo

I'm writing an application that is using libusb, and I'm working on a section that involves writing the data of the devices to an XML file.
I've realised that the program will likely need to be run with sudo, as when I tried to transfer to a device there wasn't sufficient permissions. However, when I run the program with sudo, the ofstream will no longer create the file. Why is this, and how can I fix it?
int writeDeviceList(const char* fileName, libusb_device **devs, ssize_t deviceCount)
{
std::ofstream file;
file.open(fileName, std::ios::trunc);
if(!file)
{
//Code enters here when run with root
std::cout << "\"" << fileName << "\" file failed to open\n";
return -1;
}
file << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
file << "<USB>\n";
ssize_t i;
for(i = 0; i < deviceCount; i++)
{
if(printdev(devs[i], &file) == -1)
{
return -1;
}
}
file << "</USB>\n";
file.close();
return 0;
}
One reason is if you are root on the local machine you run on, but the file is on an nfs mount of a remote machine, e.g. your normal user's home dir. Then root on the local machine will not be able to write or even open the file.

Detect if file is open in C++

Is there any way in C++ to detect if a file is already open in another program?.I want to delete and rewrite some files, but in case a file is opened I want to display an error message. I am using Windows OS.
Taking an action depending on the result of the "is file open query" is a race condition (the query returns false and then a program opens the file before your program attempts to delete it for example).
Attempt to delete the file using DeleteFile() and if it fails display the reason the file delete failed, using GetLastError(). See System Error Codes for the list of error codes (ERROR_SHARING_VIOLATION which states "The process cannot access the file because it is being used by another process.")
You can use CreateFile API function with the share mode of NULL, which opens the file for exclusive use.
You can use remove("filename") function.
you can use is_open() to check if the file is open. If it is you can close it or do somehting else.
Here is an exampe:
int main ()
{
fstream filestr;
filestr.open ("test.txt");
if (filestr.is_open())
{
filestr << "File successfully open";
filestr.close();
}
else
{
cout << "Error opening file";
}
return 0;
}
#include <iostream> // std::cout
#include <fstream> // std::ofstream
int main () {
std::ofstream ofs;
ofs.open ("example.txt");
if (ofs.is_open())
{
ofs << "anything";
std::cout << "operation successfully performed\n";
ofs.close();
}
else
{
std::cout << "Error opening file";
}
return 0;
}

ofstream doesn't work on Windows 7 hidden file

I realize that ofstream doesn't work on Windows 7 hidden file.
Here is the quick test code.
#include <fstream>
#include <iostream>
#include <tchar.h>
#include <windows.h>
int main() {
{
std::ifstream file2(_T("c:\\a.txt"));
if (file2.is_open()) {
std::cout << "ifstream open" << std::endl;
} else {
std::cout << "ifstream not open!" << std::endl;
}
}
// SetFileAttributes(_T("c:\\a.txt"), FILE_ATTRIBUTE_NORMAL);
SetFileAttributes(_T("c:\\a.txt"), FILE_ATTRIBUTE_HIDDEN);
{
std::ofstream file(_T("c:\\a.txt"));
if (file.is_open()) {
std::cout << "ofstream open" << std::endl;
} else {
std::cout << "ofstream not open!" << std::endl;
}
}
getchar();
}
Here is the output I am getting
ifstream open
ofstream not open!
If I am using FILE_ATTRIBUTE_NORMAL, ofstream will be opened successfully.
I do not run the program as Administrator. But, I do use the following linker option.
Having to turn No for Enable User Account Control (UAC) is important, if we do not start the application as Administrator. OS will help us to write the actual file to C:\Users\yccheok\AppData\Local\VirtualStore\a.txt instead of protected C:\
Does ofstream fail on Windows 7 hidden file, is an expected behaviour?
Yes. As noted in the underlying CreateFile documentation, " If CREATE_ALWAYS and FILE_ATTRIBUTE_NORMAL are specified, CreateFile fails and sets the last error to ERROR_ACCESS_DENIED if the file exists and has the FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_SYSTEM attribute."
Or more readable: CreateFile fails if both CREATE_ALWAYS and FILE_ATTRIBUTE_NORMAL are specified, and if the file has the FILE_ATTRIBUTE_HIDDEN and/or FILE_ATTRIBUTE_SYSTEM attribute.
It just so happens that ofstream calls CreateFile like this.