I have this test program:
#include "stdio.h"
int main()
{
FILE* read;
FILE* write;
write = fopen("file.txt", "w");
fwrite("Hallo", 1, 6, write);
fflush(write);
read = fopen("file.txt", "r");
//--------------------------------------
// setbuf(read, NULL); // read unbuffered
//--------------------------------------
char buf[6];
fread(buf, 1, 6, read);
printf("Should be -Hallo-: %s\n", buf);
fseek(write, 0, SEEK_SET);
fwrite("Welt", 1, 4, write);
fflush(write);
fseek(read, 0, SEEK_SET);
fread(buf, 1, 6, read);
printf("Should be -Welto-: %s\n", buf);
fclose(read);
fclose(write);
}
https://godbolt.org/z/Ysn4cs
It writes "Hallo" to a file, then reads "Hallo". Then we seek to the beginning and overwrite the file with "Welt". This should result the next read (also seek to the beginning) to read "Welto", the "o" is a leftover of "Hallo".
This code works on Linux and Windows but not on VxWorks (second fread() give "Hallo" again). It works on all 3 OSes, when I
set read to unbuffered (see comments)
reopen read before the second fread().
I read the documentation on fseek(), and I think, this is no bug, but really undefined behavior. It is not defined whether the OS must reread the file or if it can keep the buffer.
I am not a native English speaker (maybe I misunderstood something) so I am asking you if this is true.
Also, is there another solution to the two above? I would like to keep buffered reading and don`t want the overhead of reopening. Is there a function to reset the buffer once?
Related
I have the following simple code:
#include <stdio.h>
int main(){
char buffer[20] = "abc";
FILE *pFile;
pFile = fopen("myfile1.txt", "r+");
fputs("def", pFile);
fgets(buffer, 20, pFile);
printf("buffer content: %s\n", buffer);
fclose(pFile);
return 0;
}
the output is: buffer content: abc, not def as it has just been written to the file. Could someone please explain?
If you want to read randomly, you first have to tell the file reading routines, where you want to start.
Use fseekto do this.
e.g.: fseek(pFile, 0, SEEK_SET) before you try to get something with fgets.
From cppreference:
In update mode ('+'), both input and output may be performed, but output cannot be followed by input without an intervening call to fflush, fseek, fsetpos or rewind, and input cannot be followed by output without an intervening call to fseek, fsetpos or rewind, unless the input operation encountered end of file.
You're not doing any of those things between writing and reading.
yyin = fopen("input_file.txt","r");
while ((nread = fread(buf, 1, sizeof buf, yyin)) > 0){
fwrite(buf, 1, nread, stdout);
}
fclose(yyin);
yyin = fopen("input_file.txt","r");
yyparse();
fclose(yyin);
As you see, I open multiple times the same file. First I want to print the output in my cmd/terminal; then I want to start the parser. The problem is obvious: Each opening process costs resources, but the combination of fread and fwrite seems to "clean" my input file so that yyparse does not get any further input and basically stays empty.
Do you have any idea of how to make this more performant or smooth with out 2 file openings?
You can use rewind() to return to the beginning of the file again. See this documentation for more details.
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.
My C/C++ program takes a file from the command line as an argument. Reading data from 'regular files' is no problem/general programming task, but when the file comes from a 'device pipe' such as /dev/fd/63 it causes my program to crash.
To reproduce:
from your friendly neighborhood bash shell supply a 'device pipe' as a file to your application. Your app should try to read the file contents into a buffer.
./yourapp <(echo 'Hello World!'); # /dev/fd/xx containing output from echo command.
Note the above command is not redirecting the standard input of the application and that is not the intended result..
I don't think that a lot of people know this will crash their application. The application 'seed' from the Gnome project uses glib to do its I/O but it can read from these files just fine. The command 'cat' can also handle this situation gracefully. Why is it when I try to read the contents of that named pipe like a regular file my application gets the crash bug?
EDIT: relavent code section
#include <stdio.h>
int main(int argc, char **argv) {
FILE *file;
char *buffer;
unsigned long fileLen;
//Open file
file = fopen(argv[1], "rb");
if (!file) return -1;
//Get file length
fseek(file, 0, SEEK_END);
fileLen=ftell(file);
fseek(file, 0, SEEK_SET);
//Allocate memory
buffer=(char *)malloc(fileLen+1);
if (!buffer){
fprintf(stderr, "Memory error!");
fclose(file);
return -2;
}
//Read file contents into buffer
fread(buffer, fileLen, 1, file);
fclose(file);
fprintf(stdout, "Size: %i", fileLen);
free(buffer);
}
Can't call fseek on a pipe. The code shows that I was indeed trying to do such a foolish thing.
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.