std::ofstream does not show error when permission denied C++ - c++

The following code when path = "c:\" doesn't write to file c:\err.txt because permission is denied. But it doesn't generate an error at the same time. Rather, it outputs "OK".
How I can check whether the permissions would allow the write?
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
bool writeLineToErr(string path, string err_line){
std::ofstream outfile(path+"err.txt", std::ios_base::app);
if(!outfile){
cout<<"Error 1 "+path+"err.txt"+" can't open file!";
return false;
}
if(outfile.fail()){
cout<<"Error 2 "+path+"err.txt"+" can't open file!";
return false;
}
outfile << err_line << endl;
cout<<"OK";
outfile.close();
return true;
}
int main(int argc, char** argv) {
writeLineToErr("c:\\","Some Line");
return 0;
}

I'd say your code works and the write operation is actually done, but for the sake of it, add a check after the write too:
outfile << err_line << endl;
if(outfile.fail()) cout << "Error3\n";
else cout<<"OK";
On my system, I'll get your Error 1 ... can't open file if the file isn't opened for writing successfully.
Edit: Or are you running Windows with Compatibility Files virtualization still active? If so, the file will probably be in the Virtual Store, not in the real C:\err.txt path.
Example: C:\Users\username\AppData\Local\VirtualStore
If you find it there, you may find a lot of other stuff in there too. At least I did years ago when I had a similar problem. I decided to manually move (with admin rights) the few important files that some of my older programs had put there and then turn Virtual Store off. I can't find a good and simple official Microsoft link for how to turn off file and registry virtualization right now so perhaps this will do:
RegEdit:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\
Create a DWORD Key with the name EnableVirtualization and give it the value 0. If the key is already there, but set to something else than zero, change it.
There's more here:
UAC Group Policy Settings and Registry Key Settings

Related

Errno 13 when trying to open file c++

I've been working on this for a while, and I'm out of ideas. I've been trying to open and write to a file, but nothing's happening. I've been getting errno 13, but I have full permissions in the directory the file is in. If anyone has any ideas what's going on, I'd appreciate it.
Here's my code:
#include <fstream>
#include <iostream>
int main () {
std::ofstream myfile;
myfile.open ("example.txt", std::ios::out);
std::cout << errno << std::endl;
myfile << "test";
myfile.close ();
return 0;
}
I've also tried using fopen, but I didn't have any luck with that either.
Not sure what the deal was, but I got it working by moving it to a different directory. Guess it was a permissions error, but for some reason windows was saying I had permission to write to the directory.

I can't get the ofstream function to work

Hello and sorry if the answer is clear to those out there. I am still fairly new to programming and ask for some guidance.
This function should write just one of the three string parameters it takes in to the txt file I have already generated. When I run the program the function seems to work fine and the cout statement shows the info is in the string and does get passes successfully. The issue is after running the program I go to check the txt file and find it is still blank.
I am using C++17 on visual studio professional 2015.
void AddNewMagicItem(const std::string & ItemKey,
const std::string & ItemDescription,
const std::string &filename)
{
const char* ItemKeyName = ItemKey.c_str();
const char* ItemDescriptionBody = ItemDescription.c_str();
const char* FileToAddItemTo = filename.c_str();
std::ofstream AddingItem(FileToAddItemTo);
std::ifstream FileCheck(FileToAddItemTo);
AddingItem.open(FileToAddItemTo, std::ios::out | std::ios::app);
if (_access(FileToAddItemTo, 0) == 0)
{
if (FileCheck.is_open())
{
AddingItem << ItemKey;
std::cout << ItemKey << std::endl;
}
}
AddingItem.close(); // not sure these are necessary
FileCheck.close(); //not sure these are necessary
}
This should print out a message onto a .txt file when you pass a string into the ItemKey parameter.
Thank you very much for your help and again please forgive me as I am also new to stackoverflow and might have made some mistakes in formatting this question or not being clear enough.
ADD ON: Thank you everyone who has answered this question and for all your help. I appreciate the help and would like to personally thank you all for your help, comments, and input on this topic. May your code compile every time and may your code reviews always be commented.
As mentioned by previous commenters/answerers, your code can be simplified by letting the destructor of the ofstream object close the file for you, and by refraining from using the c_str() conversion function.
This code seems to do what you wanted, on GCC v8 at least:
#include <string>
#include <fstream>
#include <iostream>
void AddNewMagicItem(const std::string& ItemKey,
const std::string& ItemDescription,
const std::string& fileName)
{
std::ofstream AddingItem{fileName, std::ios::app};
if (AddingItem) { // if file successfully opened
AddingItem << ItemKey;
std::cout << ItemKey << std::endl;
}
else {
std::cerr << "Could not open file " << fileName << std::endl;
}
// implicit close of AddingItem file handle here
}
int main(int argc, char* argv[])
{
std::string outputFileName{"foobar.txt"};
std::string desc{"Description"};
// use implicit conversion of "key*" C strings to std::string objects:
AddNewMagicItem("key1", desc, outputFileName);
AddNewMagicItem("key2", desc, outputFileName);
AddNewMagicItem("key3", desc, outputFileName);
return 0;
}
Main Problem
std::ofstream AddingItem(FileToAddItemTo);
opened the file. Opening it again with
AddingItem.open(FileToAddItemTo, std::ios::out | std::ios::app);
caused the stream to fail.
Solution
Move the open modes into the constructor (std::ofstream AddingItem(FileToAddItemTo, std::ios::app);) and remove the manual open.
Note that only the app open mode is needed. ofstream implies the out mode is already set.
Note: If the user does not have access to the file, the file cannot be opened. There is no need to test for this separately. I find testing for an open file followed by a call to perror or a similar target-specific call to provide details on the cause of the failure to be a useful feature.
Note that there are several different states the stream could be in and is_open is sort of off to the side. You want to check all of them to make sure an IO transaction succeeded. In this case the file is open, so if is_open is all you check, you miss the failbit. A common related bug when reading is only testing for EOF and winding up in a loop of failed reads that will never reach the end of the file (or reading past the end of the file by checking too soon).
AddingItem << ItemKey;
becomes
if (!(AddingItem << ItemKey))
{
//handle failure
}
Sometimes you will need better granularity to determine exactly what happened in order to properly handle the error. Check the state bits and possibly perror and target-specific
diagnostics as above.
Side Problem
Opening a file for simultaneous read and write with multiple fstreams is not recommended. The different streams will provide different buffered views of the same file resulting in instability.
Attempting to read and write the same file through a single ostream can be done, but it is exceptionally difficult to get right. The standard rule of thumb is read the file into memory and close the file, edit the memory, and the open the file, write the memory, close the file. Keep the in-memory copy of the file if possible so that you do not have to reread the file.
If you need to be certain a file was written correctly, write the file and then read it back, parse it, and verify that the information is correct. While verifying, do not allow the file to be written again. Don't try to multithread this.
Details
Here's a little example to show what went wrong and where.
#include <iostream>
#include <fstream>
int main()
{
std::ofstream AddingItem("test");
if (AddingItem.is_open()) // test file is open
{
std::cout << "open";
}
if (AddingItem) // test stream is writable
{
std::cout << " and writable\n";
}
else
{
std::cout << " and NOT writable\n";
}
AddingItem.open("test", std::ios::app);
if (AddingItem.is_open())
{
std::cout << "open";
}
if (AddingItem)
{
std::cout << " and writable\n";
}
else
{
std::cout << " and NOT writable\n";
}
}
Assuming the working directory is valid and the user has permissions to write to test, we will see that the program output is
open and writable
open and NOT writable
This shows that
std::ofstream AddingItem("test");
opened the file and that
AddingItem.open("test", std::ios::app);
left the file open, but put the stream in a non-writable error state to force you to deal with the potential logic error of trying to have two files open in the same stream at the same time. Basically it's saying, "I'm sorry Dave, I'm afraid I can't do that." without Undefined Behaviour or the full Hal 9000 bloodbath.
Unfortunately to get this message, you have to look at the correct error bits. In this case I looked at all of them with if (AddingItem).
As a complement of the already given question comments:
If you want to write data into a file, I do not understand why you have used a std::ifstream. Only std::ofstream is needed.
You can write data into a file this way:
const std::string file_path("../tmp_test/file_test.txt"); // path to the file
std::string content_to_write("Something\n"); // content to be written in the file
std::ofstream file_s(file_path, std::ios::app); // construct and open the ostream in appending mode
if(file_s) // if the stream is successfully open
{
file_s << content_to_write; // write data
file_s.close(); // close the file (or you can also let the file_s destructor do it for you at the end of the block)
}
else
std::cout << "Fail to open: " << file_path << std::endl; // write an error message
As you said being quite new to programming, I have explicitly commented each line to make it more understandable.
I hope it helps.
EDIT:
For more explanation, you tried to open the file 3 times (twice in writing mode and once in reading mode). This is the cause of your problems. You only need to open the file once in writing mode.
Morever, checking that the input stream is open will not tell you if the output stream is open too. Keep in mind that you open a file stream. If you want to check if it is properly open, you have to check it over the related object, not over another one.

unable to open files c++

I'm really struggling at the moment, originally had other issues with eclipse itself, that seems to have been resolved. Code looks right to me (compared to example code for loading files) however I'm not able to load anything as the error I put in is always triggered. No building errors atm. What am I doing wrong? Tried with both eclipse (mac) and Code::blocks (win vm), both seem to be having issues. the data files themselves are in the same folder as the .cpp file.
#include <iostream>
#include <string>
#include <math.h>
#include <fstream>
using namespace std;
int main() {
cout << "Choose which data file to load (1-4)" << endl;
int file;
cin >> file;
ifstream data;
switch (file) {
case 1:
data.open("dataSet1.txt");
case 2:
data.open("dataSet2.txt");
case 3:
data.open("dataSet3.txt");
case 4:
data.open("dataSet4.txt");
}
if (!data) {
cerr << "File not Loaded" << endl;
return -1;
}
string FullData[61];
for (int i=0; i=60; i++){
data >> FullData[i];
cout << FullData[i] << endl;
}
return 0;
}
EDIT: Got the program to stop showing the error, and it seems to be loading the files, however my assign/display loop doesn't seem to be working now as it displays only the last data point over and over again.
the data files themselves are in the same folder as the .cpp file
Being in the same folder as the .cpp is not important, the dataset files should be in the same folder as the compiled binary program.
It can also be that there is a working directory setting that does not point on the directory where your dataset files are. All that is being passed into the open member function is a string which means that interpreting what that string means depends on the environment settings.
Same issue. In my case as #Gluk36 pointed, the problem was the working directory settings.
In that case, you must deselect "Use default settings" and set where the binary is. I attach you a screenshot for your reference from eclipse CDT 4.9 under linux.
You must have break statement after each case
like:
case1://something;
break;
and you must close the stream with close() function
data.close();

When will ofstream::open fail?

I am trying out try, catch, throw statements in C++ for file handling, and I have written a dummy code to catch all errors. My question is in order to check if I have got these right, I need an error to occur. Now I can easily check infile.fail() by simply not creating a file of the required name in the directory. But how will I be able to check the same for outfile.fail() (outfile is ofstream where as infile is ifstream). In which case, will the value for outfile.fail() be true?
sample code [from comments on unapersson's answer, simplified to make issue clearer -zack]:
#include <fstream>
using std::ofstream;
int main()
{
ofstream outfile;
outfile.open("test.txt");
if (outfile.fail())
// do something......
else
// do something else.....
return 0;
}
The open(2) man page on Linux has about 30 conditions. Some intresting ones are:
If the file exists and you don't have permission to write it.
If the file doesn't exist, and you don't have permission (on the diretory) to create it.
If you don't have search permission on some parent directory.
If you pass in a bogus char* for the filename.
If, while opening a device file, you press CTRL-C.
If the kernel encountered too many symbolic links while resolving the name.
If you try to open a directory for writing.
If the pathname is too long.
If your process has too many files open already.
If the system has too many files open already.
If the pathname refers to a device file, and there is no such device in the system.
If the kernel has run out of memory.
If the filesystem is full.
If a component of the pathname is not a directory.
If the file is on a read-only filesystem.
If the file is an executable file which is currently being executed.
By default, and by design, C++ streams never throw exceptions on error. You should not try to write code that assumes they do, even though it is possible to get them to. Instead, in your application logic check every I/O operation for an error and deal with it, possibly throwing your own exception if that error cannot be dealt with at the specific place it occurs in your code.
The canonical way of testing streams and stream operations is not to test specific stream flags, unless you have to. Instead:
ifstream ifs( "foo.txt" );
if ( ifs ) {
// ifs is good
}
else {
// ifs is bad - deal with it
}
similarly for read operations:
int x;
while( cin >> x ) {
// do something with x
}
// at this point test the stream (if you must)
if ( cin.eof() ) {
// cool - what we expected
}
else {
// bad
}
To get ofstream::open to fail, you need to arrange for it to be impossible to create the named file. The easiest way to do this is to create a directory of the exact same name before running the program. Here's a nearly-complete demo program; arranging to reliably remove the test directory if and only if you created it, I leave as an exercise.
#include <iostream>
#include <fstream>
#include <sys/stat.h>
#include <cstring>
#include <cerrno>
using std::ofstream;
using std::strerror;
using std::cerr;
int main()
{
ofstream outfile;
// set up conditions so outfile.open will fail:
if (mkdir("test.txt", 0700)) {
cerr << "mkdir failed: " << strerror(errno) << '\n';
return 2;
}
outfile.open("test.txt");
if (outfile.fail()) {
cerr << "open failure as expected: " << strerror(errno) << '\n';
return 0;
} else {
cerr << "open success, not as expected\n";
return 1;
}
}
There is no good way to ensure that writing to an fstream fails. I would probably create a mock ostream that failed writes, if I needed to test that.

Unable to write file in C++

I'm trying to to the most basic of things .... write a file in C++, but the file is not being written. I don't get any errors either. Maybe I'm missing something obvious ... or what?
I thought there was something wrong with my code, but I also tried a sample I found on the net and still no file is created.
This is the code:
ofstream myfile;
myfile.open ("C:\\Users\\Thorgeir\\Documents\\test.txt");
myfile << "Writing this to a file.\n";
myfile.close();
I've also tried creating the file manually beforehand, but it's not updated at all.
I'm running Windows 7 64bit if that has got something to do with this. It's like file-write operations are completely forbidden and no error messages or exceptions are shown.
You need to open the file in write mode:
myfile.open ("C:\\Users\\Thorgeir\\Documents\\test.txt", ios::out);
Make sure to look at the other options for that second argument, as well. If you're writing binary data you'll need ios::binary for example.
You should also be checking the stream after opening it:
myfile.open(...
if (myfile.is_open())
...
Update:
AraK is right, I forgot that an ofstream is in write mode by default, so that's not the problem.
Perhaps you simply don't have write/create permissions to the directory? Win7 defaults a lot of directories with special permissions of "deny all". Or perhaps that file already exists and is read-only?
Start off by turning that slash around.
Even Windows understands the slash being the other way around.
ofstream myfile("C:/Users/Thorgeir/Documents/test.txt");
You could test if there are any errors:
if (!myfile)
{
std::cout << "Somthing failed while opening the file\n";
}
else
{
myfile << "Writing this to a file.\n";
myfile.close();
}
Make sure the directory exists.
If the file exists make sure it is writeable (by you)
Check the directory you are writing into is writeable (by you)
Have you read about UAC (User Account Control) and UAC Virtualization / Data Redirection in Windows Vista and 7? It's possible that your file is actually in the Virtual Store.
User Account Control Data Redirection
Your example output directory is in Users, so I wouldn't think this would be the issue, but it's a possibility worth mentioning and something that can be very frustrating if you're not looking out for it!
Hope this helps.
This code should catch any error. Most likely it's a permissions thing if any errors are encountered. Make sure you can read/write to the folder you're creating the file in.
#include "stdafx.h"
#include <fstream>
#include <iostream>
bool CheckStreamErrorBits(const std::ofstream& ofile);
int _tmain(int argc, _TCHAR* argv[]) {
std::ofstream ofile("c:\\test.txt");
if(ofile.is_open()) {
CheckStreamErrorBits(ofile);
ofile << "this is a test" << std::endl;
if(CheckStreamErrorBits(ofile)) {
std::cout << "successfully wrote file" << std::endl;
}
}else {
CheckStreamErrorBits(ofile);
std::cerr << "failed to open file" << std::endl;
}
ofile.close();
return 0;
}
//return true if stream is ok. return false if stream has error.
bool CheckStreamErrorBits(const std::ofstream& ofile) {
bool bError=false;
if(ofile.bad()) {
std::cerr << "error in file stream, the bad bit is set" << std::endl;
bError=true;
}else if(ofile.fail()) {
std::cerr << "error in file stream, the fail bit is set" << std::endl;
bError=true;
}else if(ofile.eof()) {
std::cerr << "error in file stream, the eof bit is set" << std::endl;
bError=true;
}
return !bError;
}
Update:
I just test my code under Windows 7 Enterprize and it failed the first time (fail bit was set). Then I turn off User Account Control (UAC) and tested again and it wrote the file. That is probably the same problem you're seeing. To turn off UAC go to:
Control Panel (view by Small icons) | User Accounts | Change User Account Control settings. Set it to Never notify then click OK button. You will have to restart for the changes to take affect.
I'm curious how to make it work with UAC on, i'll look into that.
Try this:
if( ! myfile)
{
cerr << "You have failed to open the file\n";
//find the error code and look up what it means.
}
Use FileMon and look for failed WriteFile calls from your process.