fread() doesn't work but fwrite() works? - c

Why fread() doesn't work but fwrite() works?
If I get fwrite() into comments and fread() out of comments, the output file is of 0 bytes size... But if fwrite() is out of comments, the output file is of 64 bytes size..
What is the matter?
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *input = fopen( "01.wav", "rb");
if(input == NULL)
{
printf("Unable to open wave file (input)\n");
exit(EXIT_FAILURE);
}
FILE *output = fopen( "01_out.wav", "wb");
//fread(output, sizeof(char), 64, input);
fwrite(input, sizeof(char), 64, output);
fclose(input);
fclose(output);
return 0;
}

You should read from your input file, and write to your output file.
char buf[64];
fread(buf, 1, sizeof(buf), input);
fwrite(buf, 1, sizeof(buf), output);
Your code should check the return values of fread and fwrite for errors.

fread(output, sizeof(char), 64, input);
This line will read 64 bytes from the input file and store those 64 bytes at the memory that output points to. It will not write anything to the output file. Since output is a file pointer and not a pointer to an array, it does not make sense to use it like this.
fwrite(input, sizeof(char), 64, output);
This line will read 64 bytes from the memory that input points to and write them to the output file. It will not read anything from the input file. Again this won't do what you want since the memory that input points to simply contains a FILE object and not the contents of the input file.

Related

A Possible error in solution video of pset4 lab 'volume' within fread() function of header

This is the code from what Brian explains from cs50 week4 lab4
// Modifies the volume of an audio file
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
// Number of bytes in .wav header
const int HEADER_SIZE = 44;
int main(int argc, char *argv[])
{
// Check command-line arguments
if (argc != 4)
{
printf("Usage: ./volume input.wav output.wav factor\n");
return 1;
}
// Open files and determine scaling factor
FILE *input = fopen(argv[1], "r");
if (input == NULL)
{
printf("Could not open file.\n");
return 1;
}
FILE *output = fopen(argv[2], "w");
if (output == NULL)
{
printf("Could not open file.\n");
return 1;
}
float factor = atof(argv[3]);
// TODO: Copy header from input file to output file
uint8_t header[HEADER_SIZE];
fread(header, HEADER_SIZE, 1,input))
fwrite(header,HEADER_SIZE, 1, output);
// TODO: Read samples from input file and write updated data to output file
int16_t buffer;
while(fread(&buffer, sizeof(int16_t), 1, input))
{
buffer *= factor;
fwrite(&buffer, sizeof(int16_t ), 1 ,output);
}
// Close files
fclose(input);
fclose(output);
}
I am getting confused as to what fread() and fwrite() does.
It says:
while(fread(header, HEADER_SIZE, 1, input))
should not it be :
while(fread(header,sizeof(uint8_t), HEADER_SIZE, input))
since the syntax is :
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
ptr, which is the address (of the first byte) of memory into which to read the data,
size, which is the size (in bytes) of the type of data to read,
nmemb, which is the number of those types to read at once, and
stream, which is the pointer to a FILE returned by fopen.
And why are we using the address of buffer in fwrite() and fread() and not for header in fwrite() and fread()? Is the value of buffer gonna be overwritten after each loop?
It depends.
If you want to receive one complete header and then process it as a header, with the meaning of the parts of a header, then you should ask for one copy of the kind of header you want to process:
fread(header, HEADER_SIZE, 1, input)
If you want to receive a number of bytes (which happens to be the size of a header) and then process them as separate bytes (i.e. ignore the fact that together they make a header), then you should ask for many bytes:
fread(header,sizeof(uint8_t), HEADER_SIZE, input)
(With explicit permission I add the contribution by WeatherVance. It adds details on the technical consequences to my approach of trying to explain the semantic meaning.)
fread(header, 1, 44, input) and fread(header, 44, 1, input) will both attempt to read up to 44 bytes.
If only 2 bytes could be read then fread will return 2 in the first case and 0 in the second case. Because the first is trying to read 44 items of size 1 and the second wants to read 1 item of size 44.

C: How to read a file (of any format) byte by byte?

I'm attempting to write a code which will read a file byte by byte, of any type/format.
For starters I want to be able to read and write the same file, but I'm having trouble doing that for any file other than text files.
After searching here, I figured that fread/fwrite should work
unsigned char buff;
fopen_s(&input, "input_file_of_any_kind", "r");
fopen_s(&output, "new", "w");
while (!feof(input))
{
fread(&buff, 1, 1, input);
fwrite(&buff, 1, 1, output);
}
fclose(input);
fclose(output);
But when I'm trying to "copy" a jpg or pdf file, it reads only a few bytes (out of KB), so I guess my understanding here is flawed. Could you point me to the right direction?
The point of that is to reach the representation of those bytes in bits and manipulate them (and it should work for a file of any size).
To read a file of any size (byte by byte) a simple approach uses fgetc().
Open the files in binary and check results.
// fopen_s(&input, "input_file_of_any_kind", "r");
if (fopen_s(&input, "input_file_of_any_kind", "rb")) {
; // Handle error
}
Do not use while (!feof(input)).
int ch;
while ((ch = fgetc(input)) != EOF) {
fputc(ch, output);
}

Reading a text file full with null characters and texts using fread

I am trying to design a small file system.
I have created a text file to store the files data in.
int kufs_create_disk(char* disk_name, int disk_size){
FILE* file_ptr = fopen(disk_name, "w");
if (file_ptr == NULL)
return -1;
fseek (file_ptr, disk_size * 1024-1, SEEK_SET);
fwrite("", 1, sizeof(char), file_ptr); // to make a size for the file
fclose(file_ptr);
DiskName=disk_name;
return 0;
}
After writing to the file I get a file with the size I determine when I call the function.
kufs_create_disk("test.txt", 5);
which creates a file with size of 5kbs with '\0' to fill this file to the size.
I have created another function to write to this file in different places of the file which works just fine and I won't paste the code for simplicity.
When I try to read from the file using fread(), I'm not getting all the data I have written into the memory; rather I get just some of the data.
My read implementation would be:
int kufs_read(int fd, void* buf, int n){
FILE *file_ptr= fopen("test.txt","a+");
fseek (file_ptr, FAT[fd].position, SEEK_SET); //where FAT[fd].position is where I want to start my read and fd is for indexing purposes
fread(buf, 1, n, file_ptr); //n is the number of bytes to be read
FAT[fd].position = FAT[fd].position + n;
}
The thing is the file reads some of the characters written and doesn't read the rest. I did a little test by looping all over the file and checking whether every thing is being read and fread reads every thing but in the buf I only get some of the characters I've written.
The text file looks something like this:
0\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00written string1written string2 0\00\00\00\00\00\00\00\00\00\00\00\000\00\00\00\00\00\00\00\00\00\00\00\00writtenstring 3 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00
I get writtenstring1 and writtenstring2 in the buffer but I don't get writtenstring 3 for example.
Can you explain why?

C using fstat() to read size of file

I consider reading file of unknown size that I know doesn't change size in the meantime. So I intend to use fstat() function and struct stat. Now I am considering what the st_size field really means and how should I use it.
If I get the file size's in this way, then allocate a buffer of that size and read exactly that size of bytes there seems to be one byte left over. I come to this conclusion when I used feof() function to check if there really nothing left in FILE *. It returns false! So I need to read (st_size + 1) and only than all bytes have been read and feof() works correctly. Should I always add this +1 value to this size to read all bytes from binary file or there is some hidden reason that this isn't reading to EOF?
struct stat finfo;
fstat(fileno(fp), &finfo);
data_length = finfo.st_size;
I am asking about this because when I add +1 then the number of bytes read by fread() is really -1 byte less, and as the last byte is inserted 00 byte. I could also before checking with feof() do something like this
fread(NULL, 1, 1, fp);
It is the real code, it is a little odd situation:
// reading png bytes from file
FILE *fp = fopen("./test/resources/RGBA_8bits.png", "rb");
// get file size from file info
struct stat finfo;
fstat(fileno(fp), &finfo);
pngDataLength = finfo.st_size;
pngData = malloc(sizeof(unsigned char)*pngDataLength);
if( fread(pngData, 1, pngDataLength, fp) != pngDataLength) {
fprintf(stderr, "%s: Incorrect number of bytes read from file!\n", __func__);
fclose(fp);
free(pngData);
return;
}
fread(NULL, 1, 1, fp);
if(!feof(fp)) {
fprintf(stderr, "%s: Not the whole binary file has been read.\n", __func__);
fclose(fp);
free(pngData);
return;
}
fclose(fp);
This behaviour is normal.
feof will return true only once you have tried to read beyond the file's end which you don't do as you read exactly the size of the file.

Can't write PCM data to wav file

I'm trying to write PCM data (in a separate file) to the wav file I'm creating. I have already written the header and confirmed that worked but for some reason when I try to write the raw data into it, it doesn't. What I have successfully read the pcm file to a buffer and got the size of the file. The fwrite() process didn't give me an error either during compile however the resulting file is still empty. Any help is much appreciated! Thanks!
register FILE *handle;
register FILE *lever;
char filename[] = "test.wav";
handle = fopen(filename, "w");
lever = fopen("test.pcm","rb");
fseek(lever, 0, SEEK_END);
long int lSize = ftell(lever);
printf("%i \n",lSize);
rewind(lever);
char *buffer = (char*) malloc(sizeof(char)*lSize);
if (NULL == buffer) {printf("Error creating buffer \n");}
if (lSize != fread(buffer, 1, lSize, lever)) {
printf("Reading error \n");
}
fwrite(buffer, sizeof(buffer), 1, handle);
free(buffer);
fclose(lever);
fclose(handle);
Change
fwrite(buffer, sizeof(buffer), 1, handle);
into:
fwrite(buffer, lSize, 1, handle);
If you are running this under windows, it could fail because of text mode output file.
Use handle = fopen(filename, "wb");. Are you sure you have no errors while opening the files? Also your way of getting file size isn't optimal and it's better to use stat-family functions. And if malloc will fail you'll get a "Segmentation fault".
fwrite returns number of items written, or -1 on error. It sets errno so you can use perror or strerror.
EDIT: wildplasser's answer is the correct solution. Didn't notice this mistake.

Resources