C++ Connect Output Stream to Input Stream

How do you pass an OutputStream as an InputStream in C#?

So far this is the best working example I have, using Anonymous Pipes:

using( var pipeServer = new AnonymousPipeServerStream( PipeDirection.Out ) ) {
var pipeServerTask = Task.Run(
async () => {
using( var stream = getInputStream() ) {
await stream.CopyToAsync( new TransformingOutputStream( pipeServer ) );
}
pipeServer.WaitForPipeDrain();
pipeServer.Dispose();
} );

using( var client = new AnonymousPipeClientStream( PipeDirection.In, pipeServer.ClientSafePipeHandle ) ) {
MagicStreamReadingLibrary.ProcessStream( client );
}
pipeServerTask.Wait();
}

Change input stream mid-program

My previous suggestion won't work because the cat command will just join both the file and stdin as one and supply that to your program and you will eventually reach the same conclusion.

If your program needs the file, it should just read from it directly, then get the rest of its input from standard input...

#include<stdio.h>
#include<stdlib.h>
int main(void) {
int ch;
FILE* file = fopen("file.txt", "r");
if (file == NULL) {
perror("fopen");
return EXIT_FAILURE;
}

while ((ch=fgetc(file)) != EOF) {
putchar(ch);
}

fclose(file);
... // now just read from stdin

return EXIT_SUCCESS;
}

Clarify the difference between input/output stream and input/output buffer

Side note: scanf() is not the function to read input, see more here.


Now for your question: When asking about C (and, C++), e.g., the language, you should stay within the abstract concepts the language provides. So, don't start at the keyboard, that's far outside your program.

Start here: The operating system wants to deliver some input to you. Now, your C runtime provides a stream of input to your code. The stream is an abstract concept, it just means something you can continuously read from. This stream can be buffered or unbuffered, and if it's buffered, there are different modes (fully buffered or line buffered) available. You can configure all of that.

If your stream is unbuffered, this means the operating system has to wait until your code wants to read from the input stream. By default, your standard input stream is line buffered, which means your C runtime accepts the input immediately and puts it into a buffer until there is a newline -- your code calling input functions will get a result from that buffer.

Conceptually the same happens with output, just the other way around. If your output stream is for example line buffered, your C runtime will fill a buffer until there is a newline and deliver that whole line to the operating system for output. If the output is unbuffered, every single character is immediately passed to the operating system.


Disclaimer: this is still a lot simplified, but should be enough to start with.


As you ask about the term "buffer overflow" in the comments, mentioning gets() -- this is about a buffer inside your own code. With any input function that reads more than a single value/char, you have to provide your own buffer for it to store the result to. With gets(), there's no way to tell the function how large this buffer is, so it will just overflow it whenever the input available is too large. This is why gets() is ill-defined and meanwhile removed from the language C. It has nothing to do with buffers of your C runtime that are possibly used in the implementation of the I/O streams.

Connecting two streaming functions c++

It seems, you want to create something that channels the data written to Get()'s std::ostream to Put()'s std::istream. To do so you'll need to write a suitable stream which may need to deal with connecting multiple threads. If it is sufficient to read data from the stream written to by Get() after returning from Get(), you can just write to an std::ostringstream and make the written bytes available to Put() using an std::istringstream. I'm assuming you want a more direct connection and describe the general approach.

The underlying mechanics of streams are implement in stream buffers, i.e., classes derived from std::streambuf (or, if you want to support other character types like wchar_t or char32_t, the class template std::basic_streambuf. The key functions to override are

  • overflow(int_type) which is called for an output stream whenever the stream buffer's buffer is full.
  • sync() which is called for output streams when the stream's buffer needs to be flushed.
  • underflow() which is called for input stream if the stream's buffer is drained.

The details of how to implement the processing are a tad bit more involved. I have written many answers explaining various uses creating stream buffers. For a stream connecting an output stream to an input stream have a look at this answer.

Easy way to write contents of a Java InputStream to an OutputStream

Java 9

Since Java 9, InputStream provides a method called transferTo with the following signature:

public long transferTo(OutputStream out) throws IOException

As the documentation states, transferTo will:

Reads all bytes from this input stream and writes the bytes to the
given output stream in the order that they are read. On return, this
input stream will be at end of stream. This method does not close
either stream.

This method may block indefinitely reading from the
input stream, or writing to the output stream. The behavior for the
case where the input and/or output stream is asynchronously closed, or
the thread interrupted during the transfer, is highly input and output
stream specific, and therefore not specified

So in order to write contents of a Java InputStream to an OutputStream, you can write:

input.transferTo(output);


Related Topics



Leave a reply



Submit