Is it possible to convert an istream like std::cin to a FILE *? A cross-platform solution would be a plus.
EX: (FILE *)std::cin.
No, there is no standard way to obtain a FILE* from an IOStreams stream, nor vice versa.
std::cin is usually bound to file descriptor 1 (or in FILE * form, stdin).
You could just use that. Other than that, the only way to do so is either determine the file descriptor (unlikely) or the filename and use fopen to get a FP
There is no easy way using FILE* I would advise you to use fstream instead.
std::ifstream in("in.txt");
std::cin.rdbuf(in.rdbuf());
This way your redirect cin to your input file stream.
Though it is possible that your IOStreams implementation may be implemented using a FILE*, the standard does not provide any way of you accessing this information. However, it is of my knowledge that libstdc++ has a non-standard extension __gnu_cxx::stdio_filebuf, which is a wrapper around a FILE*. You can use its file() method to return a pointer to the file.
Note that this class is non-portable and non-standard. I think you're better off writing your own stream buffer that emulates its behavior.
If you have a GNU userland (just about guaranteed on Linux), take a look at fopencookie(). That allows you to adapt any source / sink to a FILE*.
The linked man-page contains in-depth guidance on how to write the adaptor.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Getting a FILE* from a std::fstream
I am working on Linux and file descriptors are the main model in this OS.
I was wondering whether is there any library or any way to retrieve the native Linux file descriptor starting from a C++ std::fstream.
I thought about boost::iostream since there is a class called file_descriptor but I understood that its purpose is different from the one I want to achieve.
Do you know some way to do that?
You can go the other way: implement your own stream buffer that wraps a file descriptor and then use it with iostream instead of fstream. Using Boost.Iostreams can make the task easier.
Non-portable gcc solution is:
#include <ext/stdio_filebuf.h>
{
int fd = ...;
__gnu_cxx::stdio_filebuf<char> fd_file_buf{fd, std::ios_base::out | std::ios_base::binary};
std::ostream fd_stream{&fd_file_buf};
// Write into fd_stream.
// ...
// Flushes the stream and closes fd at scope exit.
}
There is no (standard) way to extract the file number from an std::fstream since the standard library does not mandate how file streams will be implemented.
Rather, you need to use the C file API if you want to do this (using FILE*).
There is no official way to get the private file handle of a file stream (or actualy a std::basic_filebuf), just because it should be portable and discourage use of platform-specific functions.
However, you can do ugly hack like inheriting std::basic_filebuf and from that try to pry out the file handle. It's not something I recommend though as it will probably break on different versions of the C++ library.
There is no support of exposing file descriptor neither in standard C++ nor in libstdc++.
I create a stream by open_memstream(), fill it and then read. It works fine. But I'm confused that function documentation says: "The open_memstream() function opens a stream for writing to a buffer". But I can read it too. Does I use it in a proper way? Maybe I can read the stream because of function implementation in my platform allows to do that? And when I change a platform I will probably get an error.
But I can read it too. Does I use it in a proper way?
No, not really. Posix specifies open_memstream() is for output only. You're only supposed to write to it. You can access the data
you write via the buffer created by open_memstream(), but not with fread(), fgets() or similar.
Use fmemopen() if you want a stream you can read from too.
Maybe I can read the stream because of function implementation in my platform allows to do that?
Yes, it might be an feature of the implementation that allows you to read from the FILE* too, check its documentation.
To complete nos's answer:
POSIX 7 says http://pubs.opengroup.org/onlinepubs/9699919799/functions/open_memstream.html
The stream shall be opened for writing and shall be seekable.
so no reading, only writing.
you can't change the flags of an open file descriptor in POSIX: Reopen a file descriptor with another access?
Linux has a /proc/self/fd/n workaround however apparently.
Is it possible to delete N bytes from the end of a binary file in C++ using fstream (or something similar)? I don´t want to read the whole file, cut it and write it again, but since it´s from the end of a file it seems like it shouldn't be such a problem.
I'm not aware of a generic C++ (platform independent) way to do this without writing a new file. However, on POSIX systems (Linux, etc.) you can use the ftruncate() function. On Windows, you can use SetEndOfFile().
This also means you'll need to open the file using the native functions instead of fstream since you need the native descriptor/handle for those functions.
EDIT: If you are able to use the Boost library, it has a resize_file() function in its Filesystem library which would do what you want.
Update:
Now in C++17 you can use resize_file from filesystem
Live on Coliru
In case you want to use Qt, QFile also provides two resize() methods that allow to truncate a file.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Getting a FILE* from a std::fstream
I am working on Linux and file descriptors are the main model in this OS.
I was wondering whether is there any library or any way to retrieve the native Linux file descriptor starting from a C++ std::fstream.
I thought about boost::iostream since there is a class called file_descriptor but I understood that its purpose is different from the one I want to achieve.
Do you know some way to do that?
You can go the other way: implement your own stream buffer that wraps a file descriptor and then use it with iostream instead of fstream. Using Boost.Iostreams can make the task easier.
Non-portable gcc solution is:
#include <ext/stdio_filebuf.h>
{
int fd = ...;
__gnu_cxx::stdio_filebuf<char> fd_file_buf{fd, std::ios_base::out | std::ios_base::binary};
std::ostream fd_stream{&fd_file_buf};
// Write into fd_stream.
// ...
// Flushes the stream and closes fd at scope exit.
}
There is no (standard) way to extract the file number from an std::fstream since the standard library does not mandate how file streams will be implemented.
Rather, you need to use the C file API if you want to do this (using FILE*).
There is no official way to get the private file handle of a file stream (or actualy a std::basic_filebuf), just because it should be portable and discourage use of platform-specific functions.
However, you can do ugly hack like inheriting std::basic_filebuf and from that try to pry out the file handle. It's not something I recommend though as it will probably break on different versions of the C++ library.
There is no support of exposing file descriptor neither in standard C++ nor in libstdc++.
Is it possible to clear the contents (ie. set EOF to the beginning/reset the file) in C++ knowing just the FILE*? I'm writing to a temp file with wb+ access and wish to sometimes clear it and truncate it without adding the calls to fclose and fopen. I dont think it's possible... but if not, why not?
Thanks in advance!
It will depend on your platform. The POSIX standard provides ftruncate(), which requires a file descriptor, not a FILE pointer, but it also provides fileno() to get the file descriptor from the FILE pointer.
The analogous facilities will be available in Windows environments - but under different names.
I don't believe this can be done using just the FILE*. You can always write null data through the end of the file but that won't truncate it.
Alternately if you have access to the filename (I can't tell from the question) you could use freopen which hides the close/open/truncate into a single function call.
#include <cstdio>
freopen(null, "w", filePtr);
see http://www.cplusplus.com/reference/clibrary/cstdio/freopen/ for more. espacialy the description for the parameter filename.