Archived

This topic is now archived and is closed to further replies.

Extraenous byte being written to file. (C)

This topic is 5044 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I''m pretty new to C, and I was coding a simple file copier for practise. It works fine, except that when you copy a file, an extra byte, seemingly random, is being written to the destination file. This is my code: /* BEGIN */ #include <stdio.h> #include <stdlib.h> int main(int argv, char *argc[]) { if (argv != 3) { /* invalid command line arguments */ printf ("Usage: FC source dest"); exit (1); } FILE *src,*dest; if (!(src=fopen(argc[1],"r")) || !!(dest=fopen(argc[2],"r"))) { /* invalid files */ printf ("Invalid files specified."); exit (1); } dest=fopen(argc[2],"w"); while (!feof(src)) fputc (fgetc(src),dest); fclose (src); fclose (dest); printf ("File copied successfully."); return 0; } /* END */ Try copying a file. See? There''s an extra character being written. Why? And how can I fix it?

Share this post


Link to post
Share on other sites
try adding fputc(EOF, dest) following your while loop. The way you have it set up now you're not writing the EOF character; my guess is the system is saving you by inserting an EOF character when you close the file stream, but puts it one byte too far.

I take it back. doesn't seem to make any difference.

[edited by - Muse on February 22, 2004 12:09:31 PM]

[edited by - Muse on February 22, 2004 12:14:52 PM]

Share this post


Link to post
Share on other sites
Er...No, it doesn''t work. I''ve tried opening the files for wb and rb, and didn''t work. Then I tried also fputc''ing an EOF character at the end. Didn''t work. Tried fputc''ing EOF at the end, without binary mode. Didn''t work.
What''s up?

Share this post


Link to post
Share on other sites
First off, don't listen to muse. Files don't need an EOF at the end.

The problem is that feof() doesn't actually test whether you're at the end of the file and there's no more data to read. Instead, feof tests whether an input operation has failed due to there not being any more data to read when you were trying to read it . So what's happening is the last time the loop runs, feof() returns false even though you actually did read all the characters to be read. It doesn't return true until after you've tried and failed to read, and then written that last (invalid) character to the output file.

Try this:


...
while (1){
char c = fgetc(src);
if(feof(src)) break;
fputc (c,dest);
}
...



"Sneftel is correct, if rather vulgar." --Flarelocke

[edited by - sneftel on February 22, 2004 2:49:45 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by ZackCQB

/* BEGIN */
#include <stdio.h>
#include <stdlib.h>
int main(int argv, char *argc[]) {
if (argv != 3) { /* invalid command line arguments */
printf ("Usage: FC source dest");
exit (1);
}
FILE *src,*dest;
if (!(src=fopen(argc[1],"r")) || !!(dest=fopen(argc[2],"r"))) { /* invalid files */
printf ("Invalid files specified.");
exit (1);
}
dest=fopen(argc[2],"w");
while (!feof(src))
fputc (fgetc(src),dest);
fclose (src);
fclose (dest);
printf ("File copied successfully.");
return 0;
}
/* END */




My guess is that the fgetc(src) call returns something strange at the end of file before feof actually returns true.

I suggest you try using the fread() and fwrite() functions. They''re better for your purpose. Do something like


#define BLOCKSIZE 1024
char* buffer[BLOCKSIZE]
size_t rv;

/* open src and dest */

while( (rv=fread( buffer, BLOCKSIZE, 1, src )) > 0 ) {
fwrite( buffer, rv, 1, dest );
}

/* close src and dest, clean up */

Share this post


Link to post
Share on other sites
for( ;; )
{
int byte = getc(src);

if( feof(src) )
break;

putc( byte, dst );
}

Of course, it's much faster to read/write via a buffer(at around 1MiB or so).

[edited by - Tjoppen on February 22, 2004 2:51:33 PM]

Share this post


Link to post
Share on other sites
switched argc and argv around, but that''s just a preference thing
you fopen''d the destination twice and only fclose''d it once, so I changed that.
Seperated the two fopen commands into seperate if statements, that way if one fails, it can close the open file.

/* BEGIN */
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if (argc != 3)
{ /* invalid command line arguments */
printf ("Usage: FC source dest");
exit (1);
}
FILE *src=0,*dest=0;
if(!(src=fopen(argv[1],"rb"))
{
printf ("Invalid source specified.");
exit(1);
}
if (!(dest=fopen(argv[2],"wb")))
{
fclose(src);
printf ("Invalid dest specified.");
exit (1);
}
while (!feof(src))
fputc (fgetc(src),dest);
fclose (src);
fclose (dest);
printf ("File copied successfully.");
return 0;
}
/* END */

Haven''t tested it, but it might work better.

Share this post


Link to post
Share on other sites
quote:
Original post by Ecliptici
you fopen''d the destination twice and only fclose''d it once, so I changed that.


Look again, the first fopen actually tries to open it read-only to make sure no file is overwritten and success makes the program bail out, so that''s actually OK (except an opened file should be closed before exiting to make it clean).

Share this post


Link to post
Share on other sites