How does fwrite() work [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I have to use fwrite() instead of fputc(), but I can't understand how it works.
I have tried to use it but it writes in binary. This is the code:
while ((c = fgetc(f1)) != EOF)
{
if (fwrite(&f3, sizeof(f3), 1, f3) == EOF)
{
printf("valore iniziale di errno = %d\n",errno);
perror("errore:");
exit(1);
}
}
f1 is the file where some text is written and f3 is the file where I want to write the content of f1 but I see only binary text.

How fwrite "works"
You can start by looking at the fwrite manual. It's signature is:
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
So, let's break down each argument:
ptr is the source location of your data (where you data is).
size is the size of each element of data. fwrite writes in chunks of size bytes each time it loops.
nmemb is the number of loops fwrite will perform.
stream is the file descriptor (FILE*) of your output file.
So, with that in mind, imagine this:
// our dear string
char *str = "#SO";
// open a bogus file to write
FILE *fp = fopen(foo, "wb");
// call fwrite and store returned value
size_t ret = fwrite(str, 3, 1, fp);
This code will do the following (other than not compiling): Starting at location pointed by str, it will write 3 bytes in the file pointed by fp 1 time. However, if you did it like this:
size_t ret = fwrite(str, 1, 3, fp);
That would tell fwrite to write 1 byte to the file for every iteration it does, and it would do 3 iterations.
In your case, you read a character from f1 and want to write it to f3. Therefore, you should have something like this:
ret = fwrite(&c, sizeof(c), 1, f3);
That will read the binary character from f1 and copy it to f3.
Note that this might not be (and probably is not) the way fwrite works internally. What I presented here is the mental model I use to remember its arguments. If you actually read fwrite source code, you may find a very different implementation.
Example
So, a simple program to copy from f1 to f2 is:
#include <stdio.h>
int main(void)
{
char c;
FILE *f1 = fopen("foo.txt", "rb");
FILE *f2 = fopen("bar.txt", "wb");
size_t ret;
while((ret = fread(&c, sizeof(c), 1, f1)))
ret = fwrite(&c, sizeof(c), 1, f2);
fclose(f1);
fclose(f2);
return 0;
}

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 Updating text file using r+ mode [duplicate]

I have a program which uses stdio for reading and writing a binary file. It caches the current stream position and will not seek if the read/write offset is already at the desired position.
However, an interesting problem appears, that when a byte is read and the following byte is written, it doesn't actually get written!
Here is a program to reproduce the problem:
#include <cstdio>
int main() {
FILE *f = fopen("test.bin", "wb");
unsigned char d[1024] = { 0 };
fwrite(d, 1, 1024, f);
fclose(f);
f = fopen("test.bin", "rb+");
for (size_t i = 0; i < 1024; i++) {
unsigned char a[1] = { 255 - (unsigned char)(i) };
fflush(f);
fwrite(a, 1, 1, f);
fflush(f);
fseek(f, i, SEEK_SET);
fread(a, 1, 1, f);
printf("%02X ", a[0]);
}
fclose(f);
return 0;
}
You are supposed to see it write the bytes FF down to 00, however only the first byte is written because it does not follow a fread immediately.
If it seeks before fwrite, it acts correctly.
The problem happens on Visual Studio 2010/2012 and TDM-GCC 4.7.1 (Windows), however it works on codepad which I guess is due to it being executed on Linux.
Any idea why this happens?
C99 §7.18.5.3/6 (quoted from N869 final draft):
“When a file is opened with update mode (’+’ as the second or third character in the
above list of mode argument values) […] input shall not be directly followed by output without an
intervening call to a file positioning function, unless the input operation encounters end-
of-file.”

Can't read whole file in c

I'm trying to move content from one file to another.
My code:
char *path = extractFileName(args[1]);
if (path == 0)
return -1;
FILE *input = fopen(path, "r");
rewind(input);
fseek(input, 0L, SEEK_END);
long sz = ftell(input);
printf("sz: %ld\n", sz);
rewind(input);
size_t a;
FILE *result = fopen("result.mp3", "w");
size_t counter = 0;
char buffer[128];
while ((a = fread(&buffer[0], 1, 128, input)) != 0) {
fwrite(&buffer[0], 1, a, result);
counter += a;
}
printf("%d\n", counter);
printf("ferror input: %d\n", ferror(input));
printf("feof input: %d\n", feof(input));
After execution it prints
sz: 6675688
25662
ferror input: 0
feof input: 16
As far as I know it means that C knows that size of input file is 665kb but returns eof when I try to read more than 25662 bytes. What I'm doing wrong?
Since your output filename is result.mp3, it's a safe bet you're dealing with non-textual data. That means you should be opening your files in binary mode - "rb" and "wb" respectively. If you're running this code on Windows, not doing that would explain the behavior you're seeing (On that platform, reading a particular byte (0x1A) in text mode causes it to signal end of file even when it's not actually the end), and using binary mode will fix it. On other OSes, it's a no-op but still clues the reader into your intentions and the type of data you're expecting to work with, and is thus a good idea even if it's not strictly needed on them.

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?

how does work setvbuf() in C [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
can someone explain me how does int setvbuf(FILE *stream, char *buffer, int mode, size_t size) C function works?
I think it sets a buffer for a file stream and stores data in the buffer allocated by setvbuf in size_t size chunks of data, am I right? And when the buffer is full it is flushed?
sorry I am new here
I assume you did search google, but you need some help understanding what you have found:
I am quoting interchangeably gnu documentation and cppreference:
int setvbuf (FILE *stream, char *buf, int mode, size_t size)
After opening a stream (but before any other operations have been
performed on it), you can explicitly specify what kind of buffering
you want it to have using the setvbuf function. The facilities listed
in this section are declared in the header file stdio.h.
The arguments description:
stream - the file stream to set the buffer to
buffer - pointer to a buffer for the stream to use
mode - buffering mode to use. It can
be one of the following values:
_IOFBF full buffering
_IOLBF line buffering
_IONBF no buffering
size - size of the buffer
If you switch for the c documentation in cppreference you will find the following example:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int file_size;
char buffer[BUFSIZ];
FILE * fp = fopen("test.txt","w+");
if (setvbuf(fp,buffer,_IOFBF,BUFSIZ) != 0)
{
perror("setvbuf()");
fprintf(stderr,"setvbuf() failed in file %s at line # %d\n", __FILE__,__LINE__-3);
exit(EXIT_FAILURE);
}
/* Exhibit the contents of buffer. */
fputs ("aaa",fp);
printf("%s\n", buffer);
fputs ("bbb",fp);
printf("%s\n", buffer);
fputs ("ccc",fp);
printf("%s\n", buffer);
file_size = ftell(fp);
printf("file_size = %d\n", file_size);
fflush (fp); /* flush buffer */
printf("%s\n", buffer);
fputs ("ddd",fp);
printf("%s\n", buffer);
fputs ("eee",fp);
printf("%s\n", buffer);
rewind(fp); /* flush buffer and rewind file */
char buf[20];
fgets(buf,sizeof buf,fp);
printf("%s\n", buf);
fclose(fp);
return 0;
}
Output:
aaa
aaabbb
aaabbbccc
file_size = 9
aaabbbccc
dddbbbccc
dddeeeccc
aaabbbcccdddeee
Pay attention for the following things:
What happens when you fflush the FILE *fp.
What buffer contains after fputs string to fp.
What happens when you rewind(fp), reread from the file all you have been written.
Don't be afraid of documentation/ manual pages, if you get used to them and read them you will be a great developer, moreover now you are familiar with http://en.cppreference.com/, which is very good source to get start with new API functions, good luck.

Resources