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.
Related
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?
Could someone tell me why the file doesn't change? It works when I use rewind or fseek but not otherwise.
What's the standard way of using fputs after fgets. The file indicator is at position 9 so fputs must write after that, but it doesn't do anything.
In file:
abcd efgh ijkl mnor
In source code:
char c;
char str[15];
FILE *fp = fopen("d:\\data.txt","r+");
fgets(str, 10, fp);
// fseek(fp, 9, SEEK_SET);
// rewind(fp);
printf("%d\n", ftell(fp));
// ftel shows that it's in "9".
printf("%s", str);
fputs(str, fp);
// why its not working
fclose(fp);
Regarding the definition of fopen/'+' in the C standard (e.g. as in this online C standard draft), switching from reading to writing requires an intermediate call to a file positioning function (emphasis are mine):
7.21.5.3 The fopen function
(7) When a file is opened with update mode ('+' as the second or third
character in the above list of mode argument values), both input and
output may be performed on the associated stream. However, output
shall not be directly followed by input without an intervening call to
the fflush function or to a file positioning function (fseek, fsetpos,
or rewind), and 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. Opening (or creating) a text file
with update mode may instead open (or create) a binary stream in some
implementations.
So I'd suggest you write the following code to overcome your problem:
fseek ( fp , 0, SEEK_CUR);
fputs(str, fp);
The MS documentation for fopen says this:
When the "r+", "w+", or "a+" access type is specified, both
reading and writing are enabled (the file is said to be open for
"update"). However, when you switch from reading to writing, the input
operation must encounter an EOF marker. If there is no EOF, you
must use an intervening call to a file positioning function. The file
positioning functions are fsetpos, fseek, and rewind. When you
switch from writing to reading, you must use an intervening call to
either fflush or to a file positioning function.
I have been trying out some file io and have written the following:
#include <stdio.h>
int main(){
char stuff [80];
FILE *file;
file=fopen("hello.cheese", "w+");
fprintf(file, "%s", "cheese");
fscanf(file, "%s", stuff);
printf("%s", stuff);
fprintf(file, "\n%s", stuff);
fclose(file);
return 0;
}
All this does is put ^A in the file (next line underneath cheese) and print nothing.
You might want to read closely fopen description, especially
When a file is opened with update mode ( '+' as the second or third character in the mode argument), both input and output may be performed on the associated stream. However, the application shall ensure that output is not directly followed by input without an intervening call to fflush() or to a file positioning function ( fseek(), fsetpos(), or rewind()), and input is not directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.
You used 'w+' mode, which allows reading and writing, but did not flush, nor rewind file pointer after write.
As a side note, Your code could use some error checking (NULL != file).
#include <stdio.h>
#include <stdlib.h>
#define FILE_NAME "ff.txt"
int main() {
char x[10],y[10];
FILE *fp;
fp = fopen(FILE_NAME, "r+");
if (fp == NULL) {
printf("couldn't find %s\n ",FILE_NAME);
exit(EXIT_FAILURE);
}
fprintf(fp,"Hello2 World\n");
fflush(fp);
fscanf(fp,"%s %s",x,y);
printf("%s %s",x,y);
fclose(fp);
return 0;
}
Here's a boiled down version of what I am trying to do. This code doesn't print anything in the console. If I remove the fprintf call, it prints the first 2 strings in the file, for me its Hello2 World. Why is this happening? Even after I fflush the fp?
After fprintf(), the file pointer points to the end of the file. You can use fseek() to set the filepointer at the start of the file:
fprintf(fp,"Hello2 World\n");
fflush(fp);
fseek(fp, 0, SEEK_SET);
fscanf(fp,"%s %s",x,y);
Or even better as suggested by #Peter, use rewind():
rewind(fp);
rewind:
The end-of-file and error internal indicators associated to the stream
are cleared after a successful call to this function, and all effects
from previous calls to ungetc on this stream are dropped.
On streams open for update (read+write), a call to rewind allows to
switch between reading and writing.
It is always best to check the return code of fscanf() too.
To avoid buffer overflow, you can use:
fscanf(fp,"%9s %9s",x,y);
I was wondering what's the best way to read in a filename in C when the name is echoed on the command line, as in: if I type in
echo test.txt | a1
how would I access the test.txt using
fopen(fname, "r");?
When you pipe data from one program to another it's as if you typed the output of the first into the second. In this case the file name can be read from stdin, and one way to read it is with the fgets function.
Read data from the standard input.
Process the data.
#include <stdio.h>
char buf[1024];
while (fgets(buf, sizeof buf, stdin))
{
printf("Read line: '%s'\n", buf);
FILE * fp = fopen(buf, "r");
if (fp)
{
// process the file
fclose(fp);
}
else
{
printf("No such file: %s\n", buf);
}
}
The obvious caveat is that the file name may be longer than 1023 characters; read the manual for fgets for details on how to detect this.
The way it's written, you'll do one processing attempt per line, and the program stops when the input stream ends.
You're trying to read from stdin, which means you could use fread (man 3 fread on *nix, here if you aren't.) to read from it.
stdin is just a name for a standard file-descriptor, so you can read from it like any other file.