c++ open file in one line - c++

I've got these two lines of code
ifstream inputFile;
inputFile.open("data.txt");
I vaguely remember there being a way to do something similiar using one line of code instead.
How to do it in one line?

You can use the constructor to specify the filename:
ifstream inputFile("data.txt");
See the details for std::basic_ifstream (constructor).
explicit basic_ifstream( const char* filename,
std::ios_base::openmode mode = ios_base::in );
First, performs the same steps as the default constructor, then associates the stream with a file by calling rdbuf()->open(filename, mode | std::ios_base::in) (see std::basic_filebuf::open for the details on the effects of that call). If the open() call returns a null pointer, sets setstate(failbit)

Related

C++ file handle

I am trying to implement a file handle class similar to the one in Bjarne Stroustrup's FAQ page. (Scroll to "Why doesn't C++ provide a 'finally' construct".) Unlike his example, however, I want to use C++ file streams instead of a FILE*.
Right now, I am considering creating a FileHandleBase class, or something similarly named, and two derived classes—one for input files and one for output files. Below is the implementation I wrote as a proof-of-concept; keep in mind that it is very simple and unfinished.
class FileHandle {
public:
FileHandle(const char* fn, ios_base::openmode mode = ios_base::in | ios_base::out) {
file.open(fn, mode);
// Check to make sure file is open
}
FileHandle(const string &fn, ios_base::openmode mode = ios_base::in | ios_base::out) {
file.open(fn, mode);
// Check to make sure file is open
}
~FileHandle() {
file.close();
}
private:
fstream file;
};
I would like to know if this is a viable way of making a file handle, that is, whether my inheritance idea is good. I also want to know the best way to deal with the ios_base::openmode parameter because the C++ reference page for std::ifstream says this:
Note that even though ifstream is an input stream, its internal filebuf object may be set to also support output operations.
In what cases would an ifstream be used for output operations, and, similarly, when would an of stream be used for input operations; and should I restrict the options for the ios_base::openmode parameter for my file handle class(es)? That way my input file handle would only handle input operations, and the output version would only handle output operations.
In what cases would an ifstream be used for output operations, and, similarly, when would an ofstream be used for input operations
You would open an output file stream with an std::ios_base::in openmode and vice-versa for an input file stream if you would still like to perform those associated operations using the internal std::filebuf object, which is accessible by stream->rdbuf(). Note that the streams std::ofstream and std::ifstream will still be able to perform output and input respectively even if they are opened with opposite openmodes.
int main() {
std::ofstream stream("test.txt");
stream << "Hello" << std::flush;
stream.close();
stream.open("test.txt", std::ios_base::in);
char buffer[SIZE] = {};
stream.rdbuf()->sgetn(buffer, SIZE);
std::cout << buffer << std::endl;
}

Compilation results in an error when trying to compile code containing binary ifstream

I am running into a problem with the accessing a binary file via the input file stream class (ifstream).
My approach starts with the following calling function:
void ReadFile(vector<string>& argv, ostream& oss){
string FileName = argv.at(2) + "INPUT" ;
ifstream BinFile ;
OpenBinaryFile(FileName, BinFile) ;
return ;
}
The called function looks like this:
void OpenBinaryFile(string& FileName, ifstream& BinFile){
using namespace std ;
BinFile(FileName.c_str(),ifstream::binary | ifstream::in) ;
}
When I try to compile this simple scheme using gcc version 4.9.2 I get the following error:
error: no match for call to ‘(std::ifstream {aka std::basic_ifstream<char>}) (const char*, std::_Ios_Openmode)’
BinFile(FileName.c_str(),ifstream::binary | ifstream::in) ;
^
I've tried to get the caret ("^") placed exactly where the compiler did.
What's going on here? I am baffled.
Thanks!
There are two ways of opening a stream.
During construction, in a declaration:
std::ifstream BinFile(filename, std::ifstream::binary | std::ifstream::in);
After construction, using the std::ifstream::open function:
std::ifstream BinFile;
BinFile.open(filename, std::ifstream::binary | std::ifstream::in);
In your question you are attempting to mix the two. This results in an attempt to call the non-existent "function call operator" operator() on the object BinFile.
As written, you were calling a constructor with the object that had already been constructed on the stack of the calling routine. See the constructor documented at http://www.cplusplus.com/reference/fstream/ifstream/ifstream/

How can the current file be overwritten?

For the following code:
fstream file("file.txt", ios::in):
//some code
//"file" changes here
file.close();
file.clear();
file.open("file.txt", ios::out | ios::trunc);
how can the last three lines be changed so that the current file is not closed, but "re-opened" with everything blanked out?
If I am understanding the question correctly, you'd like to clear all contents of the file without closing it (i.e. set the file size to 0 by setting EOF position). From what I can find the solution you have presented is the most appealing.
Your other option would be to use an OS-specific function to set the end of file, for example SetEndOfFile() on Windows or truncate() on POSIX.
If you're only looking to begin writing at the beginning of the file, Simon's solution works. Using this without setting end of file may leave you in a situation where you have garbage data past the last position you wrote though.
You can rewind the file: put back the put pointer to the beginning of the file, so next time you write something, it will overwrite the content of the file.
For this you can use seekp like this:
fstream file("file.txt", ios::in | ios::out); // Note that you now need
// to open the file for writing
//some code
//"something" changes here
file.seekp(0); // file is now rewinded
Note that it doesn't erase any content. Only if you overwrite it so be careful.
I'm guessing you're trying to avoid passing around the "file.txt" parameter and are trying to implement something like
void rewrite( std::ofstream & f )
{
f.close();
f.clear();
f.open(...); // Reopen the file, but we dont know its filename!
}
However ofstream doesn't provide the filename for the underlying stream, and doesn't provide a way to clear the existing data, so you're kind of out of luck. (It does provide seekp, which will let you position the write cursor back to the beginning of the file, but that wont truncate existing content...)
I'd either just pass the filename to the functions that need it
void rewrite( std::ostream & f, const std::string & filename )
{
f.close();
f.clear();
f.open( filename.c_str(), ios::out );
}
Or package the filestream and filename into a class.
class ReopenableStream
{
public:
std::string filename;
std::ofstream f;
void reopen()
{
f.close();
f.clear();
f.open( filename.c_str(), ios::out );
}
...
};
If you're feeling over zealous you could make ReopenableStream actually behave like a stream, so that you could write reopenable_stream<<foo; rather than reopenable_stream.f<<foo but IMO that seems like overkill.

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;
}

std::stringstream and std::ios::binary

I want to write to a std::stringstream without any transformation of, say line endings.
I have the following code:
void decrypt(std::istream& input, std::ostream& output)
{
while (input.good())
{
char c = input.get()
c ^= mask;
output.put(c);
if (output.bad())
{
throw std::runtime_error("Output to stream failed.");
}
}
}
The following code works like a charm:
std::ifstream input("foo.enc", std::ios::binary);
std::ofstream output("foo.txt", std::ios::binary);
decrypt(input, output);
If I use a the following code, I run into the std::runtime_error where output is in error state.
std::ifstream input("foo.enc", std::ios::binary);
std::stringstream output(std::ios::binary);
decrypt(input, output);
If I remove the std::ios::binary the decrypt function completes without error, but I end up with CR,CR,LF as line endings.
I am using VS2008 and have not yet tested the code on gcc. Is this the way it supposed to behave or is MS's implementation of std::stringstream broken?
Any ideas how I can get the contents into a std::stringstream in the proper format? I tried putting the contents into a std::string and then using write() and it also had the same result.
AFAIK, the binary flag only applies to fstream, and stringstream never does linefeed conversion, so it is at most useless here.
Moreover, the flags passed to stringstream's ctor should contain in, out or both. In your case, out is necessary (or better yet, use an ostringstream) otherwise, the stream is in not in output mode, which is why writing to it fails.
stringstream ctor's "mode" parameter has a default value of in|out, which explains why things are working properly when you don't pass any argument.
Try to use
std::stringstream output(std::stringstream::out|std::stringstream::binary);