We have a huge codebase in HP-UX and we are porting them in RH-Linux. I am facing the problem of making the following code work in gcc -
ofstream ofs;
int fd = open(fileName, openState, openMode));
func(fd);
......
......
const Boolean func(const int fileDescriptor)
{
ofs.attach(fileDescriptor);
if (! ofs)
{
closeIt();
ofs.attach(fileDescriptor);
if (! ofs)
return(FAIL);
}
return(SUCCESS);
}
Here one file is opened and then the ofs variable is attached to that file descriptor.
Unlike HP-UX compiler, gcc doesn't have the attach() function. So how I can make the code compatible? I tried to solve the problem in various ways like how it is described here - Gerhard Wesp - Re: Attaching cout || cerr to an ostream or here - [c++] How to create a std::ofstream to a temp file? - Stack Overflow. But nothing is helping this particular issue since fd is a filedescriptor and not a filebuf. Can you please help me out?
There's no standard, portable way to do this. Like ghostbusters, you're not supposed to cross the streams. But g++ iostreams do have some extensions to make it possible. Adapting an example found here I tried this:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <iostream>
#include <ext/stdio_filebuf.h> // __gnu_cxx::stdio_filebuf
using namespace std;
int main(void)
{
std::string str;
int fd=open("whatever", O_RDONLY); // Get an FD
FILE *fp=fdopen(fd, "r"); // convert it into a FILE *
// create a file buffer(NOT an iostream yet) from FILE *
__gnu_cxx::stdio_filebuf<char> fb (fp, ios_base::in);
istream fs (&fb); // create a stream from file buffer
fs >> str;
cout << str << endl;
return(0);
}
Testing this on a file containing 'asdf' it does print asdf, so while a bit tortuous it does actually work. It being that tortuous also makes it plain that you are using an extension, which is probably the point...
I don't know if the stdio_filebuf closes the FILE * for you when it goes out of scope or not.
First of all thanks a ton to your post - appreciate your time and effort to help me out! I took long time to reply here because of some other urgent work.
I took your help and wrote the following program which creates an ostream object from the file descriptor -
#include <fstream.h>
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <ext/stdio_filebuf.h> // __gnu_cxx::stdio_filebuf
int main()
{
int fd;
FILE *fp;
if (-1 == (fd=open("/tmp/test.txt", (O_WRONLY|O_CREAT|O_APPEND), 0666)))
{
cout<<"Unable to open file"<<endl;
exit(1);
}
cout << "File Descriptor # is: " << fd << endl;
if (NULL == (fp = fdopen(fd, "a")))
{
cout<<"fdopen failed"<<endl;
close(fd);
exit(1);
}
// create a file buffer(NOT an iostream yet) from FILE *
__gnu_cxx::stdio_filebuf<char, std::char_traits<char> > fb (fp, std::ios_base::out);
ostream os(&fb);
os << "Hello World!" << endl;
close(fd); //ostream doesn't have the close() function
return 0;
}
To create the ofstream object in the same way we have to do the following -
#include <fstream.h>
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <ext/stdio_filebuf.h> // __gnu_cxx::stdio_filebuf
int main()
{
int fd;
FILE *fp;
std::ofstream ofs;
if (-1 == (fd=open("/tmp/test.txt", (O_WRONLY|O_CREAT|O_APPEND), 0666)))
{
cout<<"Unable to open file"<<endl;
exit(1);
}
cout << "File Descriptor # is: " << fd << endl;
if (NULL == (fp = fdopen(fd, "a")))
{
cout<<"fdopen failed"<<endl;
close(fd);
exit(1);
}
// create a file buffer(NOT an iostream yet) from FILE *
__gnu_cxx::stdio_filebuf<char> fb(fp, std::ios::out);
ofs.std::ios::rdbuf(&fb);
ofs << "Hello World!" << endl;
ofs.close();
return 0;
}
Both the programs and running fine and will be a ready references for other users facing the same problem.
Once again thanking you for your generous support!