Neuquert
Neuquert

Reputation: 69

Copy file in C doens't seem to work completely

For my programming course I have to make a program that copies a file.

This program asks for the following:

The files required to copy are .WAV audio files. I tried this with an audio sample of 3 seconds.

The thing is that I do get a file back, for it to be empty. I have added the fclose and fopen statements

while((ch = fgetc(input)) != EOF)
{
  fputc(ch, output);
}

I hope someone can point out where I probably made some beginners mistake.

Upvotes: 0

Views: 108

Answers (1)

Peter - Reinstate Monica
Peter - Reinstate Monica

Reputation: 16016

The little while loop you show should in principle work if all prerequisites are met:

  • The files could be opened.
  • If on a Microsoft operating system, the files were opened in binary mode (see below).
  • ch is an int.

In other words, all problems you have are outside this code.

Binary mode: The CR-LF issue

There is a post explaining possible reasons for using a carriage return/linefeed combination; in the end, it is the natural thing to do, given that with typewriters, and by association with teletypes, the two are distinct operations: You move the large lever on the carriage to rotate the platen roller or cylinder a specified number of degrees so that the next line would not print over the previous one; that's the aptly named line feed. Only then, with the same lever, you move the carriage so that the horizontal print position is at the beginning of the line. That's the aptly named carriage return. The order of events is only a technicality.

DOS C implementations tried to be smart: A C program ported from Unix might produce text with only newlines in it; the output routines would transparently add the carriage return so that it would follow the DOS conventions and print properly. Correspondingly, CR/LF combinations in an input file would be silently converted to only LF when read by the standard library implementations.

The DOS file convention also uses CTR-Z (26) as an end-of-file marker. Again, this could be a useful hint to a printer that all data for the current job had been received.

Unfortunately, these conventions were made the default behavior, and today are typically a nuisance: Nobody sends plain text to a printer any longer (apart from the three people who will comment under this post that they still do that).

It is a nuisance because for files that are not plain text silent data changes are catastrophic and must be suppressed, with a b "flag" indicating "binary" data passed in the fopen mode argument: To faithfully read you must specify fopen(filename, "rb"), and in order to faithfully write you must specify fopen(filename, "wb").

Empty file !?

When I tried copying a wave file without the binary flags the data was changed in the described fashion, and the copy stopped before the first byte with the value 26 (CTRL-Z) in the source. In other words, while the copy was corrupt, it was not empty. By the way, all wave files start with the bytes RIFF, so that no CTR-Z can be encountered in the first position.

There are a number of possibilities for an empty target file, the most likely of which:

  • You didn't emit or missed an error message regarding opening the files (does your editor keep a lock on the output?), and the program crashed silently when one of the file pointers was null. Note that error messages may fail to be printed when you make error output on standard out: That stream is buffered, and buffered output may be lost in a crash. By contrast, output to stderr is unbuffered exactly to prevent message loss.
  • You are looking at the wrong output file. This kind of error is surprisingly common. You could perform a sanity check by deleting the file you are looking at, or by printing something manually before you start copying.

Generally, check the return value of every operation (including your fputc!).

Upvotes: 3

Related Questions