Reputation: 11
Platform : Windows
Language : C
I have two programs:
.jpg
file in binary mode(_setmode(_fileno(stdin), _O_BINARY) ,_setmode(_fileno(stdout), _O_BINARY)
using fread and outputs the using fwrite to stdout.read/write
done in binary mode). But I can see that output image is corrupted and not same as input.
I executed program1.exe | program2.exe
in powershell.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
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