Brain
Brain

Reputation: 11

STDIN, STDOUT not streaming correct output when used with pipe in windows

Platform : Windows

Language : C

I have two programs:

But if I write a program to read a file in binary mode and write it to another file in binary mode, then outputs are same. Problem occurs only when I use stdin and stdout.

Program 1:

int main()
{
    int mode, fd, ret;
    errno_t err;
    int a = _setmode(_fileno(stdin), _O_BINARY);
    a = _setmode(_fileno(stdout), _O_BINARY);
    //freopen("ooo", "wb", stdout);
    //char in[4096];
    char in[4096];
    char o[100];
    int size = sizeof(in);
    FILE* fpIn, * fpOut, * fp3, * fin;
    //int  a =_setmode(_fileno(stdin), _O_BINARY);
    int x = sizeof(in);
    fpOut = fopen("out", "wb");
    //int bb = _setmode(_fileno(fpOut), _O_BINARY);
    fin = fopen("pic.jpg", "rb");
    //fin = fopen("in.txt", "rb");
    //a = _setmode(_fileno(fin), _O_BINARY);
    //int length = fread(&in, sizeof(in), 1, stdin);
    int count = 0;
    
    while ((count = fread(in, 1, sizeof(in), fin)) != 0)
    {
        fwrite(in, 1, count, stdout);
        fflush(stdout);
    }
    fclose(fpOut);  
}

Program 2:

int main()
{
int a = _setmode(_fileno(stdin), _O_BINARY);
     a = _setmode(_fileno(stdout), _O_BINARY);
    //freopen("ooo.txt", "wb", stdin);
    char in[4096];
    
    int o[100];
    int size = sizeof(in);
    FILE* fpIn, * fpOut, *fp3,*fin;
    //int  a =_setmode(_fileno(stdin), _O_BINARY);
    int x = sizeof(in);
    fpOut = fopen("out", "wb");
    //int bb = _setmode(_fileno(fpOut), _O_BINARY);
    fin = fopen("pic.jpg", "rb");
    a = _setmode(_fileno(fin), _O_BINARY);
    //int length = fread(&in, sizeof(in), 1, stdin);
    int count=0;

    while ((count = fread(in, 1, sizeof(in), stdin)) != 0)
        fwrite(in, 1, count, fpOut);


    fclose(fpOut);
}

The requirement of program is to allow user to input arbitrary input through stdin and write it to a file.

Upvotes: 1

Views: 578

Answers (1)

ryyker
ryyker

Reputation: 23218

EDIT

Added to address conversation in comments as its relevance may be important to OP. Paying attention to the current encoding settings of your cmd.exe program may be important to do some of the things you are asking for. That topic is discussed in in this very detailed answer. and serve to explain why you are seeing what you are seeing.

Your only stated requirement is "The requirement of program is to allow user to input arbitrary input through stdin and write it to a file."

An example using fread and fwrite is at bottom, but unless you are required to use these, consider a simpler approach...

Borrowing from the comments, this example is the simplest implementation that does exactly what you described you needed. (And was tested using Windows-10.)

<ctrl-c> to exit, then read file out.txt...

int main(int argc, char *argv[]) {

    int c = 0;
    FILE *fp = fopen(".\\out.txt", "w");
    if(fp)
    {
        while( ( c = fgetc(stdin) ) != EOF ) 
        { 
            fputc(c, stdout); //out to screen
            fputc(c, fp); //to file
        }
        fclose(fp);    
    }
    return 0;
}

Reading and outputting a binary file is just about as simple, just change the arguments in fopen() for binary read/write, and point to an image you want to transfer:

No need of course to use <cntl-c>, program will exit when file copy is done.

int main(int argc, char *argv[]) {

    int c = 0;
    FILE *fpIn = fopen(".\\so_1.jpg", "rb");
    FILE *fp = fopen(".\\out.jpg", "wb");
    if(fp)
    {
        while( ( c = fgetc(fpIn) ) != EOF ) { fputc(c, fp); }
        fclose(fp);    
    }
    return 0;
}

If it is required that you use fread/fwrite, then here is a very minimal example of doing exactly the same task using your code with some modifications: (removed calls to setmode, in buffer sized to file it will contain, removed while loop, see in-code comments.)

int main(int argc, char *argv[]) 
{
    int count = 0;
    unsigned long len = fsize(".\\so_1.jpg");//start by getting in file size
    char in[len];//create buffer with exact count of bytes in file
    FILE *fpIn = fopen(".\\so_1.jpg", "rb");
    if(fpIn)
    {
        FILE *fpOut = fopen(".\\out.jpg", "wb");
        if(fpOut)
        {
            count = fread(in, 1, sizeof(in), fpIn);//no need for while loop here, just check for > 0 
            if(count > 0)
            {
                fwrite(in, 1, count, fpOut);
            }
            fclose(fpOut);
        }
        fclose(fpIn);
    }
    return 0;
}

unsigned long fsize(char* file)
{
    if(!file) return 0UL;
    FILE * f = fopen(file, "r");
    if(!f) return 0UL;
    if(fseek(f, 0, SEEK_END) != 0) return 0UL;
    unsigned long len = (unsigned long)ftell(f);
    fclose(f);
    return len;
}

Upvotes: 1

Related Questions