Reading Binary Data from Stdin

C read binary stdin

I had it right the first time, except, I needed ntohl ... C Endian Conversion : bit by bit

Reading binary data from stdin

Use the -u command line switch to force Python 2 to treat stdin, stdout and stderr as binary unbuffered streams.

C:> type mydoc.txt | python.exe -u myscript.py

Python 2.7 - How to programmatically read binary data from stdin

Just remove the buffer for python2:

import sys

input = sys.stdin.read()

Best way to read binary file c++ though input redirection

If it were me I would probably do something similar to this:

const std::size_t INIT_BUFFER_SIZE = 1024;

int main()
{
try
{
// on some systems you may need to reopen stdin in binary mode
// this is supposed to be reasonably portable
std::freopen(nullptr, "rb", stdin);

if(std::ferror(stdin))
throw std::runtime_error(std::strerror(errno));

std::size_t len;
std::array<char, INIT_BUFFER_SIZE> buf;

// somewhere to store the data
std::vector<char> input;

// use std::fread and remember to only use as many bytes as are returned
// according to len
while((len = std::fread(buf.data(), sizeof(buf[0]), buf.size(), stdin)) > 0)
{
// whoopsie
if(std::ferror(stdin) && !std::feof(stdin))
throw std::runtime_error(std::strerror(errno));

// use {buf.data(), buf.data() + len} here
input.insert(input.end(), buf.data(), buf.data() + len); // append to vector
}

// use input vector here
}
catch(std::exception const& e)
{
std::cerr << e.what() << '\n';
return EXIT_FAILURE;
}

return EXIT_SUCCESS;
}

Note you may need to re-open stdin in binary mode not sure how portable that is but various documentation suggests is reasonably well supported across systems.

Re-direct binary file content from STDIN into a C program

If you can include a batch file into your solution, i.e. one that will feed the contents of a file into a shell variable, then use the shell variable as a command line argument to the executable, then the following steps will work:

  • Copy this into a batch file, say read.bat:
    set /p in= < somebinaryfile.bin
CProgram.exe "%in%"

Note: Unless somebinaryfile.bin location is listed in the path environment variable, it should include <path>, eg: C:\dir1\dir2\somebinaryfile.bin

  • Then execute from command line:

    read.bat

Note, you need to set stdin to binary mode at the beginning of your main() function. for example using _setmode(_fileno(stdin), O_BINARY);

My test code is posted here
(Note: it is not fully tested, but works as far as reading a binary file from stdin and transferring binary content to a new file.)

Windows10, using GNU GCC compiler

#include <windows.h>
#include <io.h> // _setmode()
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> // O_BINARY
#include <time.h>

void make_binary(void);

int main(int argc, char *argv[])
{
_setmode(_fileno(stdin), O_BINARY);//sets stdin mode to binary

//make_binary();//used to produce binary file for testing input
//comment after first use.

FILE *fp = fopen(".\\new_binary.bin", "wb");
if(fp)
{
fwrite(argv[1], sizeof(unsigned char), 1000, fp);
fclose(fp);
}
return 0;
}

//Create some binary data for testing
void make_binary(void)
{
FILE *fp = fopen(".\\binary.bin", "wb");
unsigned char bit[1000];
srand(clock());
for(int i=0; i< 1000; i++)
{
bit[i] = (unsigned char)rand();
}
size_t count = fwrite(bit, sizeof(*bit), 1000, fp);
printf("Number of bytes written to binary.bin = %u\n", count);
fclose(fp);
}

Yield from a typical session:

Sample Image

I want to interpret stdin as a binary file. Why is freopen failing on Windows?

Why freopen() might fail in general

The C standard says:

If filename is a null pointer, the freopen function attempts to change the mode of
the stream to that specified by mode, as if the name of the file currently associated with
the stream had been used. It is implementation-defined which changes of mode are
permitted (if any), and under what circumstances.

Presumably, your implementation doesn't allow the changes you're trying to make. On Mac OS X, for example, the man page for freopen() adds:

The new mode must be compatible with the mode that the stream was originally opened with:

  • Streams originally opened with mode "r" can only be reopened with that same mode.
  • Streams originally opened with mode "a" can be reopened with the same mode, or mode "w".
  • Streams originally opened with mode ``w'' can be reopened with the same mode, or mode "a".
  • Streams originally opened with mode "r+", "w+", or "a+" can be reopened with any mode.

With that said, on Mac OS X (where b is a no-op anyway), you'd be OK.

Why freopen() fails on Windows specifically

However, you're on Windows. You need to learn how to find and read the documentation. I use a Google search with the term 'site:msdn.microsoft.com freopen' for whatever function I'm looking for. That specific search yields the manual for freopen() where it says:

If path, mode, or stream is a null pointer, or if filename is an empty string, these functions invoke the invalid parameter handler, as described in Parameter Validation. If execution is allowed to continue, these functions set errno to EINVAL and return NULL.

That's the documented behaviour: it is also the behaviour you are seeing. The manual for your system is helpful. It basically says "thou shalt not".

How to fix the input mode of standard input on Windows

I note that in my answer to your previous question, I pointed to _setmode():

However, it is more likely that you need _setmode():

_setmode(_fileno(stdin), O_BINARY);

This is the advice that is given in the answers to the question that deamentiaemundi pointed to.

I note in passing that the Microsoft manual page for setmode() says:

This POSIX function is deprecated. Use the ISO C++ conformant _setmode instead.

This is a curious comment because POSIX does not standardize a function setmode() in the first place.

You can find Microsoft's documentation for fileno(). It too has the spiel about POSIX (but this time it is accurate; POSIX does specify fileno()) and refers you to _fileno().



Related Topics



Leave a reply



Submit