c++: ifstream delete contents of a file? [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am using following function:
int getline_count()
{
boost::smatch resultc;
string sLine;
int line_add_tmp;
ifstream infile;
infile.open("scripts.txt", ios_base::in);
if (!infile){
cerr << "scripts.txt could not be opened!" << endl;
}
else {
getline(infile, sLine);
if (boost::regex_match(sLine, c)) {
line_add = 2;
}
else {
line_add = 1;
}
return line_add;
infile.close();
}
}
Intension for the above function is to test if the first line in the file contains '// new' If true, 2 is returned. If false, 1 is returned. This works fine so far.
What I am confused about is that after the run the file scripts.txt is empty. How can that be since
1.) The '// new' line was correctly identified as I am getting '2' returned (running on an empty file returns 1 as expected). So it can't be that during opening the file scripts.txt it was overwritten with an empty file
2.) ifstream was designed to read only
What is it what I am missing?
Edit:
Definition for c is
static const boost::regex
c("^(\\/)(\\/)(new|New| new| New)"); // Regexp for line count

An ifstream should never manipulate your file. You will need to look elsewhere for your problem, it's not inside this code. Your best bet is to provide a Minimal, Complete, and Verifiable example that demonstrates your problem.
However, you should check your coding, you are missing essentials like error handling and treating compiler warnings. Most likely, if your other code looks the same, that's the source of your problem.
Personally, I'd write your function like this:
bool first_line_in_file_matches(const std::string& filename, const boost::regex& c)
{
std::string line;
std::ifstream infile(filename.c_str());
if (!infile)
{
cerr << filename << " could not be opened!" << endl;
// TODO: THROW AN EXCEPTION MAYBE? OR RETURN FALSE? EXIT HERE
}
return getline(infile, line) && boost::regex_match(line, c);
}

This function will not clear the contents of the file. So if in fact the file is cleared it is cleared externally to getline_count.
To prove this lets inspect the functionality of each call on ifstream relative to the file:
ifstream::open This will only clear the file if the mode is set to ios_base::trunk
ifstream::operator bool This is a const method so the ifstream cannot be modified
ifstream::getline TLDR: This can only extract, not write to a file:
Internally, the function accesses the input sequence by first constructing a sentry object (with noskipws set to true). Then (if good), it extracts characters from its associated stream buffer object as if calling its member functions sbumpc or sgetc, and finally destroys the sentry object before returning.
ifstream::~ifstream This is implicitly declared, so it simply destroys the object, closing the file; if this deleted file contents no one would ever have been able to use an ifstream
The recommended steps to finding the culprit of the file clearing are:
Ensure that you are looking at the correct file and don't have some process external to your code which is clearing the file
Search your code for "scripts.txt" something else has to access the file by name and debug it
Disable writing to "scripts.txt" and see if you can locate the code that fails to write to the file

Related

ofstream returning error "No matching function to call std::basic_ofstream<char>::close(const char [14])"

Need help fixing my code, not sure what's wrong. I'm using C++11, trying to write a vector to a file by individually writing each struct. The section of code returning an error is:
string craigSave = "craigSave.txt";
ofstream file(craigSave.c_str());
file.open("craigSave.txt");
for (int i=0; i<finalVector.size(); i++){
file << finalVector[i]<<endl;
}
file.close("craigSave.txt");
cout<<"Thanks for shopping!"<<endl;
done = true;
The error returned is on the "file.close" line and is:
error: no matching function for call to 'std::basic_ofstream::close(const char [14])'
I research on this error seems to point to needing to use char* as an argument instead of a string, but I'm using C++11, so it should accept strings. Also it is strange that there is no error for the file.open line, as all research shows the error being there, not at file.close
Just use file.close();, there's no need to pass the file name again.
See http://www.cplusplus.com/reference/fstream/ofstream/close/.
Also, ofstreams are RAII objects, which means that the file will automatically be closed once the ofstream object goes out of scope (see do I need to close a std::fstream?):
{
ofstream out("name");
// do something with out...
} // out.close is called automatically

Classes reading one word from file C++

This is my program and it supposed to get text word by word from file Team.txt but it says it can't open the file. I tried showing directory directly to the file still the same answers. I think I got something here:
class Team
{
public:
string name;
string dificulty;
string section;
};
void GetTeamInfo(class Team);
int main()
{
Team ko;
GetTeamInfo(ko);
cout << ko.name;
cout << ko.dificulty;
cout << ko.section;
system("PAUSE");
}
void GetTeamInfo(Team)
{
std::ifstream fd;
fd.open("Team.txt");
Team ko;
if (fd.is_open())
{
fd >> ko.name;
fd >> ko.dificulty;
fd >> ko.section;
}
else
{
std::cout << "Mistake can't open file 'Team.txt'\n";
}
}
It doesn't work because your argument handling is all wrong.
The declaration
void GetTeamInfo(Team)
tells the compiler that GetTeamInfo is a function which takes an argument of type Team, but you don't give it a name so you can't use the argument anywhere inside the function.
If you want to use the passed argument you should give it a name:
void GetTeamInfo(Team ko)
You then don't have to declare the variable ko inside the function.
However, this is not going to work anyway, because arguments are by default passed by value, that means arguments are copies of the values from the caller. And changing a copy will of course not change the original. So what you should do it pass the argument by reference:
void GetTeamInfo(Team& ko)
All of this is very basic C++ knowledge, and any good book or tutorial should have learned you this very early.
As for the problem of the program not being able to open your file, there are multiple possible causes for that problem:
Your IDE (Integrated Development Environment) is having one current directory for your program, and the file is not in that directory. This can be changed with project settings.
The file is actually not where you think it is.
The file simply doesn't exist.
On systems such as Linux and Mac OSX filenames are case sensitive, and the actual file doesn't have a capital 'T' in its name.

C++ create ifstream/ofstream in a class, associated with pre-made text file

I am having a problem associating an ifstream read and ofstream print to a pre-made text file called finances.txt. This is within a class called Data. So far, this is what I've tried:
I declared ifstream read and ofstream print in the class header file. Then, in the cpp file:
Data::Data(string n, string d)
:name(n),
date(d)
read(name)
print(name)
{
cout << "name = " << name << endl;
read.open(name);
print.open(name);
//...
}
I also tried this, without declaring anything in the header:
Data::Data(string n, string d)
:name(n),
date(d)
{
ifstream read(name);
ofstream print(name);
//...
And just different variations of this kind of thing. The syntax is always correct in the sense that I don't get any errors, but whenever it runs, it acts like the file doesn't exist and creates a new one named finances.txt, which in turn erases all of the text that was in the original. I have done this correctly before and just can't remember what I did and what I am doing incorrectly here.
I am a little confused as to what exactly you are trying to do?
Are you trying to append to the file? Because when you call
ofstream print(name) you are writing over the file that you are reading in.
So if you want to append to that same file you have to add.
fstream::app in the declaration of the ofstream

fstream won't print to file

The following code will print something to a file
std::fstream fout ("D_addr.txt", std::fstream::app);
fout << pkt->Addr() << std::endl;
flush(fout);
fout.close();
While debugging, I watched pkt->Addr() and it has some values. The fout line is passed without problem. Also the file D_addr.txt is created. However after closing the file, the file size is zero! nothing has been written to it.
Where is the problem?
This is not your actual code I guess and if it is I would start with that Addr() function of yours.
Note that fstream::close "closes the file currently associated with the object, disassociating it from the stream. Any pending output sequence is written to the physical file." flush(fout); can be omitted.
You should also specify std::fstream::out flag. "If the function is called with any value in that parameter the default mode is overridden, not combined." So instead of std::fstream::app you should pass std::fstream::app | std::fstream::out.
I'm wondering if you're not using the wrong class. If you want to write to a file, use std::ofstream, and not std::fstream. In particular, the constructor of std::ofstream forces the ios_base::out bit when calling rdbuf()->open; the constructor of std::fstream doesn't (so you're opening the file with neither read nor write access).
And you probably want to check the error status: did the open succeed, and after the close (or the flush), did all of the writes succeed. The usual way of doing this is just:
if ( fout ) {
// All OK...
}
if ( !fout ) {
// Something went wrong.
}
After the open (the constructor), you can use fout.is_open(), which has the advantage of being a little bit more explicit with regards to what you are checking for.
First of all, flush() and fout.close() do not make any harm, but are not needed here, because when fout gets destroyed the file will be closed (and flushed) as part of fstream destructor.
Second, you should use an ofstream or alternatively add the flag std::ios::out to the openmode parameter.
Try something along the lines of:
{
uint64_t x = 42;
std::fstream of("test.txt", std::ios::app);
of << x << std::endl;
}

Checking existence of a txt file with C++ code

First of all, i'd to establish that i do have the text file in my Folders directory. Im using visual studio and it is where my source code is compiling.
The code below should demonstate why its not working. In visual studio.
int main( const int argc, const char **argv )
{
char usrMenuOption;
const char *cFileName = argv[ 1 ];
checkName( cFileName ); // supplying the checkName function with contents of argv[1]
usrMenuOption = getUsrOption(); // calling another function
fgetc(stdin);
return 0;
}
ifstream *openInputFile( const char *cFileName )
{
// this function might be the pronblem.
ifstream *inFile;
inFile = new ifstream;
inFile->open( cFileName, ios::in );
return inFile;
}
bool checkName( const char *cFileName )
{
// it works fine if i use a regular ifstream obj and not the one from the function
ifstream *inFile;
inFile = openInputFile( cFileName );
inFile->open( cFileName, ios::in );
if ( inFile->good() )
{
return true;
}
else
{
cout << '"' << cFileName << '"' << ": File does not exist! " << endl;
return false;
}
}
It does work if i use a non-pointer object for the ifstream.
however i need to open all of my input files this way, using the function i made.
I'm a little confused because i did not have this issue compiling in dev-cpp
You have a few options:
The one you've tried - opening the file.
Using stat.
Using GetFileAttributes.
Using FindFirstFile.
The only way to guarantee that it exists and that you can use it is to open it. If you use other methods you end up with a race condition (because the file could be deleted or locked after you check to see if it exists.
EDIT: You have a couple of other issues in your code. Firstly, you allocate a infile via new, but you never delete it. Secondly, you call open twice.
That's a poor way to test for existence: because if the file is open by another process, then the file exists but you can't open it.
A better way to test might be to use the GetFileAttributes Function: if it doesn't return INVALID_FILE_ATTRIBUTES then the file exists.
If you don't mind using Boost, there is a simple function boost::filesystem::exists( path ) that would be useful to you I guess !
I always check ifs.is_open() where ifs is a ifstream.
To check for the existence of a file (POSIX.1 compliant):
#include <unistd.h>
if (! access (file_name, F_OK))
{
// File exists.
}
How do i check if a file exists using ANSI C++?
#include <fstream>
inline bool FileExists(const char * filename)
{
return std::ifstream(filename);
}
You're trying to open the file twice inside checkName(): the first time in the constructor call inside the call to openInputFile(), the second time inside checkName() itself. Why the second call to open()?
I don't know what happens when an ifstream with an already-open file attempts to open() another file, but it won't be good, and it may well depend on the exact library implementation (hence the different behaviour between Dev-C++ and MSVC++). In short, don't do it.
There is at least one other bug: You aren't closing inFile anywhere inside checkName().
But Anyway, Do This Instead
Really, it's better not to have a separate checkName() function -- just have openInputFile() attempt to open the file, and if it fails, report the error right there and/or return a NULL pointer (or even throw an exception). That way, the operation is "atomic" -- as things stand, if the file exists at the time checkName() is called but is deleted before a subsequent call to openInputFile(), your code will get very confused.