I would like my program to read the standard output produced by another application. I am aware that I can use popen to do that and use fread to read that output.
Do you know whether is possible to use read (and possibly open)? I am working in LINUX with C/C++
You can get a file descriptor for read() by calling int fd = fileno(fp) for the FILE *fp you have got from popen(). But be aware that you must not mix calling read() and fread()!
EDIT
If you want to avoid popen(), you have to use pipe(), fork(), exec..() and dup2() like it's done here
Related
Well, the subject says it all, basically.
I have a command-line utility that may be used interactively or in scripts, using pipes or i/o redirection. I am using cin and cout for i/o, and I want to write an extra EOL at the end if the output is console, so that user prompt will start from the next line. Within scripts this would be harmful.
Can I assume cin == 0, cout == 1? I understand that there is no clean way to get the file descriptor of a stream. Or is it?
If using Linux (and probably other unixes, but definitely not Windows) you could try isatty.
There's no direct way of extracting the file descriptor from the C++ stream. However, since in a C++ program both cout as well as stdout exist and work at the same time (C++ by default provides synchronisation between stdio and iostream methods), your best bet in my opinion is to do a isatty(fileno(stdout)).
Make sure you #include <unistd.h>.
It is possible to use rdbuf() to change the destination of std::cin and std::cout inside your program. If you don't do that, it is probably quite safe to assume that cin = 0, cout=1 and clog and cerr both = 2 as the C++ standard states that they are synchronized with C stdin, stdout and stderr and those have per POSIX those file descriptors at startup.
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.
I have the following code:
int buffer_max_size = 1024;
char* buffer = new char[buffer_max_size]
FILE* cout_file = fdopen(cout_pipe[0], "r");
while (fread( &buffer[0], sizeof(char),sizeof(char)*buffer_max_size, cout_file) != 0 )
{...}
cout_file is of type FILE* and is connected to a binary's stdout.
That binary outputs some text on its std_out at 5 sec intervals.
It seems that fread is blocking until the cout_file contains buffer_max_size bytes.. Is that normal?
I would like to be able to read what is in the pipe right now without blocking.. Is that possible?
If you want non-blocking I/O, use the OS's read and fcntl functions.
The <stdio.h> API (and also <fstream>) perform additional buffering and may automatically retry reads which end early (for example due to being interrupted by a signal), so they cannot be guaranteed to provide non-blocking I/O even if the underlying file descriptor is configured for it.
Not all OSes will use these POSIX names. In that case your options are platform-specific code (for example, on Windows you would be using ReadFile and SetNamedPipeHandleState), or using a wrapper library such as Boost ASIO to abstract the differences. But make sure that your wrapper is designed to expose non-blocking behavior, otherwise it will cause the same pain as <stdio.h>
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.