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

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/

Related

c++ open file in one line

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)

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

Param syntax for substituting boost filtering_stream for std::ofstream

Some basic questions about boost filtering_streams. I have dozens of functions that take a parameter of std::ofstream&
void foo(std::ofstream& outStream)
{
// lots of operations, like this:
outStream << "various bits of text";
}
void StreamSomeTextToFile(char* fileName)
{
ofstream myFileStream(fileName, ios::out | ios::app | ios::binary);
foo(myFileStream);
myFileStream.close();
}
Now I'd like to use the boost filtering_stream to output to a compressed ZIP file. The commonly cited boost filtering_streams test code for packing and unpacking compiled, linked, and worked perfectly for me. I'd like to substitute the filtering_stream:
void StreamSomeCompressedTextToFile(char* fileName)
{
ofstream myFileStream(destPath, std::ios_base::out | std::ios_base::app | std::ios_base::binary);
boost::iostreams::filtering_streambuf<boost::iostreams::output> myCompressedFileStream;
myCompressedFileStream.push(boost::iostreams::zlib_compressor());
myCompressedFileStream.push(myFileStream);
foo(myCompressedFileStream); // I can't just pass myCompressedFileStream to foo(std::ofstream&), right?
myFileStream.close();
}
THREE QUESTIONS:
1) Do all my functions that previously accepted std::ofstream& outStream need to now accept a parameter of type boost::iostreams::filtering_streambuf& ? Or is there a proper parameter type so those numerous ("foo") functions could work with EITHER type of stream type?
2) In my simple test cases, I was not able to use stream operator syntax with the filtering_streambuf:
myCompressedFileStream << "some text";
this generated the the error: no match for 'operator<<'. I similarly had compile errors with write():
error: 'class boost::iostreams::filtering_streambuf<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char>, boost::iostreams::public_>' has no member named 'write'
3) In the common test case example code (below), I was confused that I could not locate the file "hello.z" after it had been created. The unpack code (also below) clearly references it -- so where can it be found? NOTE: the location was finally discovered: it was in the /Library/Preferences/
void pack()
{
std::ofstream file("hello.z", std::ios_base::out | std::ios_base::binary);
boost::iostreams::filtering_streambuf<boost::iostreams::output> out;
out.push(boost::iostreams::zlib_compressor());
out.push(file);
char data[5] = {'a', 'b', 'c', 'd', 'e'};
boost::iostreams::copy(boost::iostreams::basic_array_source<char>(data, sizeof(data)), out);
file.close();
}
void unpack()
{
std::fstream file("hello.z", std::ios_base::in | std::ios_base::binary);
boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
in.push(boost::iostreams::zlib_decompressor());
in.push(file);
boost::iostreams::copy(in, std::cout);
}
BTW: XCode 3.2.6, GNU 4.0, OS X 10.6.8
Taking the questions in order:
1: Stream buffer objects (like boost::iostream::filtering_streambuf or std::streambuf) are not interchangeable with stream objects (such as std::ostream or boost's implementation). That being said, you can pass a streambuf object like "myCompressedFileStream" to a constructor of an ostream object (this boost iostream tutorial provides a decent explanation with examples). And because boost's streambufs are compatible with those in the standard library, you need not change any of the functions accepting std::ostream/ofstream references. You just can't pass streambufs as streams.
2: Same as above, the insertion operator is defined for streams, not streambufs.
3: Normally, files without a preceding directory name are created in the directory of the executable. That being said, I've found at times Finder has been somewhat slow reflect files updated/created by non-Finder processes. I didn't experience those problems in Terminal using ls. No idea if that's related to your problem, though.
SUCCESS!
A combination of hints from Paul Schellin (above) and several on Boost-users resulted in the answer:
1) Boost User Frédéric pointed out that "nothing happen[s] until output_file [filtering_ostream] is destroyed. So enclose in { }". This was the essential missing piece, because I was trying to do file.close() on my ofstream BEFORE my filtering_streambuf was destroyed. That explained why the file was empty!
Re-reading the documentation revealed:
"By default, if the Device at the end of the chain is popped
or if the filtering_stream is complete when it is destroyed,
all the filters and devices in the chain are closed using the
function close. This behavior can be modified using the member
function set_auto_close"
This states is there is no need to "pop" the compressor() or the ofstream (file) off the filtering_stream's stack, nor to call close(). Just destruct the filtering_stream object, and everything gets written out and cleaned up. An obscure detail, and one that goes counter to what one might expect.
3) Boost User Holger Gerth questioned why I was using filtering_streambuf when I could've been using filtering_stream. Truth is, I wasn't sure, however, in my experiments I could neither construct the ostream (which I required to pass to other functions) from the filtering_stream, nor could I pass the filtering_stream in place of the ostream I required.
Even after reading several articles on filtering_streambuf vs filtering_stream, I'm still mystified how and why (FOR MY PURPOSE) I would use the filtering_stream over constructing an ostream from a filtering_streambuf.
SO, TO RECAP:
1) Construct a separate ostream from the filtering_streambuf, and pass THAT to foo() or to the Stream Insertion operator (i.e. <<).
2) Don't call myFileStream.close();

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

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.