So here is the problem:
I want to write some text to a text file, but I got across some weird situations:
SAMPLE 1:
int main()
{
FILE *file = fopen("structures.txt", "a+"); // open the file for reading & writing
int choice = 0;
if(file == NULL)
puts("Unable to open text file");
else {
do {
scanf("%d", &choice);
fprintf(file, "This is testing for fprintf...\n");
}while(choice > 0);
}
fclose(file);
return 0;
}
In this version of the program, nothing ever gets written to the text file & I can't understand why. But the strangest thing for me is next:
SAMPLE 2:
int main()
{
FILE *file = fopen("structures.txt", "a+"); // open the file for reading & writing
int choice = 0;
if(file == NULL)
puts("Unable to open text file");
else {
do {
scanf("%d", &choice);
fprintf(file, "This is testing for fprintf...\n");
fclose(file); // Added this line, the writing works
}while(choice > 0);
}
fclose(file);
return 0;
}
After adding fclose(file); directly after the fprintf call, the program successfully writes :
This is testing for fprintf...
to the text file.
My questions are:
Does that mean that I have to open my text file whenever I want to
write some text to it & close it directly afterwards ?
Does fclose() has anything to do with the writing process ?
What are the factors that prevent fprintf() from working ?
(1st sample)
How can I open & close the text file just ONCE, at the start of the program & at the end of it (respectively) guaranteeing at the same time that my program will work flawlessly ?
Does that mean that I have to open my text file whenever I want to write some text to it & close it directly afterwards ?
No, but it may mean you need to close the file before the contents you've written will actually be flushed and written out to the file.
Does fclose() has anything to do with the writing process ?
Most file streams are buffered. Meaning that each write goes to memory. It is not written to disk until the buffer is full or you call close.
What are the factors that prevent fprintf() from working ? (1st sample)
Anything you get significantly wrong.
How can I open & close the text file just ONCE, at the start of the program & at the end of it (respectively) guaranteeing at the same time that my program will work flawlessly ?
You could call something like fflush(). But are you sure you tried this and the file contained nothing even after you finally closed the file at the end?
I solved the problem using int fflush (FILE *stream) (which #Jonathan hinted at).
Flushing output on a buffered stream means transmitting all
accumulated characters to the file. There are many circumstances when
buffered output on a stream is flushed automatically:
When you try to do output and the output buffer is full.
When the stream is closed.
When the program terminates by calling exit.
When a newline is written, if the stream is line buffered.
Whenever an input operation on any stream actually reads data from its file.
So basically, I just had to call fflush() after the call to fprintf() :
fprintf(file, "This is testing for fprintf...\n");
fflush(file);
Related
In the code below, extra spcaes (may be around 300 space) are getting appended if I write data after seeking the file pointer to the start position after the line
fseek(fp1,0,SEEK_SET);
If I comment second fputs() function call, there is no issue.
Also the inputted data is not getting appended at the end, instead only spaces are getting appended.
I am unable to identify the problem.
I am using TDM-GCC-64 compiler.
For testing purpose, file1.txt had contents "Welcome to You All" at the beginning.
Inputted data: "Today"
Output after execution of the program: "Todayme to You All" followed by many spaces.
int main()
{
FILE *fp1;
char ch;
char data[50];
fp1=fopen("file1.txt", "r+");
if(fp1==NULL)
{
printf("Error in Opening the file\n");
return(0);
}
printf("Read and Write Mode. The data in the file is\n");
while((ch=getc(fp1))!=EOF)
{
putc(ch,stdout);
}
// Write some data at the end of the file
printf("\nEnter some data to be written to the file\n");
gets(data);
fseek(fp1,0,SEEK_END);
fputs(data,fp1);
fseek(fp1,0,SEEK_SET);
fputs(data,fp1);
printf("data in file after write operation is\n");
while((ch=getc(fp1))!=EOF)
{
putc(ch,stdout);
}
fclose(fp1);
return 0;
}
You should check the fine print in the fopen documentation:
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.
Reading and writing might be buffered, but still share a single file position. Switching modes without alerting the runtime (fseek) could mess up the buffering. Like you have noticed!
I want to open a file, read its contents, and then append a line to the file. I thought I should use the "a+" flag for the task.
I have a function which opens a file and returns a pointer to this file.
FILE* open_weekly_disk_file(char* filename){
FILE* weekly_log;
weekly_log = fopen(filename, "a+");
//weekly_log = fopen(filename, "r");
if(! weekly_log){
printf("The attempt to open the weekly log failed!\n");
return NULL;
} else{
return weekly_log;
}
}
Then I have a function which calls the function above and uses scanf to read contents from the file:
void sample_function(char* filename){
FILE* log;
char token[100], current_read[100];
int limit;
log = opened_weekly_disk_file(filename);
// The problem happens here
for(limit=0; limit < TOKEN_NUMBER; limit++){
if(fscanf(log, "%s%s", &token, ¤t_read) == 2){
printf("%s %s\n", token, current_read);
}
}
...
}
This code works when I use:
weekly_log = fopen(filename, "r");
But does not work when I change the "r" flag to "a+". I get a Segmentation fault right before the for loop.
That is because the mode spec "a" opens a file for appending, with the file pointer at the end. If you try to read from here, there is no data since the file pointer is at EOF. You should open with "r+" for reading and writing. If you read the whole file before writing, then the file pointer will be correctly positioned to append when you write more data.
If this is not enough, please explore ftell() and fseek() functions.
from this SO QA
from the man page:
a+
Open for reading and appending (writing at end of file). The file is
created if it does not exist. The initial file position for reading is
at the beginning of the file, but output is always appended to the end
of the file.
Answer:
There is just one pointer which initially is at the start of the file
but when a write operation is attempted it is moved to the end of the
file. You can reposition it using fseek or rewind anywhere in the file
for reading, but writing operations will move it back to the end of
file.
So, the problem is not the fact that the file is opened in append mode, because it is not, as far as reading from it is concerned.
The problem lies in what your code does in those three dots
log = opened_weekly_disk_file(filename);
...
The code quite probably writes to the file, making the file cursor move to the end of it before the reading occurs.
i am trying to read integers from a file and fscanf doesn't work well with this code.
fp=fopen("record.dat","r");
if(fp==NULL)
{
printf("Another reading error");
}
else
{
printf("\nstarting to read\n");
i=0;
while(i<10)
{
if(fscanf(fp,"%d",&temp)>0)
printf("%d\n",temp);
i++;
}
fclose(fp);
}
the file contains 10 numbers which are delimited by a new line character. This code doesn't produce or print anything. What is the problem with the code and pls help me with it.
EDIT
the access mode as w+ or r isn't giving me a correct expected answer.
You are opening the file as a writable file instead of readable.
You must change "w+" to "r"
w+ The file is created if it does not exist, otherwise it is truncated. The stream is positioned at the beginning of the file.
"w+" actually opens file for reading and writing. However, file is truncated to 0 length.
That might be the cause of printing blank lines.
Try "r+" (opens the file for reading and writing, without truncation) or "r".
I am trying to get a basic understanding on how to use fputc in C. I have read some documentation that is out there and believed I had it right. But every time I try to use the script I wrote by executing ./fputc > test.txt where text.txt is a text file with one line of text.
This is my script:
int
main(int argc, char **argv){
int ch;
FILE *input;
input = fopen("text.txt", "w+");
while ((ch = getchar()) != EOF){
fputc(ch, input);
}
fclose(input);
return 0;
}
I get no errors on compilation and for some reason the script does not reach EOF at the end of the text file. Shouldn't the getchar return EOF when it reached the end of the text file?
The text (text.txt) file does not appear to be edited, although it is created. So somewhere in my while loop something is going wrong.
I am new to C programming (if you couldn't tell) and this little script has me befuddled.
Any help would be appreciated, or any links to sites with further detail would also be great.
Cheers,
S.
What you in essence say is:
Console: Run my_program and write anything it outputs to test.txt.
Program: Open text.txt and write any input to stdin to that file.
Your console normally have three standard streams stdin, stdout and stderr. These streams you can redirect. If you are on Windows also look at i.e. redirection.
When you say ./my_prog > test.txt, what you tell your console, (not my_prog), is to write anything my_prog writes to stdout to the file test.txt.
If you in your code say i.e. printf("Hello");, then Hello would be written to the file test.txt.
If you had turned your redirection around by saying ./my_prog < test.txt instead, would be; stream the file test.txt to my_prog. Which, in turn, if there was any text in test.txt would result in a copy of test.txt to text.txt.
Now in your code you say:
int main(void)
{
int ch;
FILE *input;
/* Here you open a handle to the file text.txt for reading and writing */
input = fopen("text.txt", "w+");
while ((ch = getchar()) != EOF) { /* get next char from stdin */
fputc(ch, input); /* write that char to the handle input */
}
fclose(input); /* close the handle */
return 0;
}
So what happens, the way you run it, is:
In your code:
Open text.txt
Wait for input (data entered to stdin) - typically user entering text to console, passed to program when Enter is pressed.
In console:
Redirect anything from my_prog to test.txt.
You say:
the script does not reach EOF
Well, as it reads from stdin it will only (not without exception) get EOF under two conditions.
If you redirect a file to your program. I.e. ./my_prog < foo.txt (notice <, not >).
- What would happen then is that my_prog would read the data from the file foo.txt and when that file ends your program would receive a EOF. And, hence quit.
If you manually enter EOF to stdin.
- On Linux and OSX Ctrl-D, on Windows Ctrl-Z
Now, if you test this by typing text to console remember that write actions like fputc()is buffered. What this mean is that the data is not written to the file right away, but only when a given amount of data is in buffer, fflush() is called, stream is closed, you turn off buffering, etc.
Also; if you run your program. Enter text, enter some more text, and then hit Ctrl-C to abort the program it is a big chance you end with no data in your text.txt.
The reason for this is that the program is killed and thereby fclose() never called, and hence no flush to file.
On your further endeavors in programming it would be a very good idea to make a habit of not presuming anything. I.e. do not presume fopen() is OK.
FILE *fh;
char *outfile = "foo.txt";
if ((fh = fopen(outfile, "w")) == NULL) {
fprintf(stderr,
"Unable to open file %s\n --",
outfile);
perror(" fopen() ");
return 1;
}
Most functions has a way to check if operation was a success. I.e:
if (fputc(ch, fh) != ch) { err ...
This will make your code a lot safer, give you hints on where it fails etc.
Some links:
Look at redirection links at top of post.
Look at the functions in stdio.h (good overview), stdio.h (examples etc.). I.e.:
stdin
stdout
stderr
fopen()
fflush()
setvbuf()
setbuf()
...
getchar returns the next character from the standard input (stdin).
It is equivalent to getc with stdin as its argument.
Hence, your code reads from standard input instead of FILE* input.
Use fgetc here.
fgetc returns the character currently pointed by the internal file position indicator of the specified stream. The internal file position indicator is then advanced by one character to point to the next character.
So, Use fgetc to read from a file:
while ((ch = fgetc(input)) != EOF)
your program and the shell are both writing the same file. you should remove the output redirection > test.txt from your command line
I have a random access file opened in "r+b" mode with records of equal length. Can I change the contents of a record after reading it and overwrite in place?
I tried the following code but on running I get: Segmentation fault(core dumped)
#include<stdio.h>
int main()
{
struct tala {
int rec_no;
long file_no;
};
FILE *file_locking;
struct tala t,f;
file_locking = fopen("/path/to/my/file.bin", "rb+");
t.rec_no = 1;
t.file_no = 3;
if (fwrite(&t, sizeof(struct tala),1,file_locking)==0)
printf("Error opening file");
t.rec_no=0;
rewind(file_locking);
if (fwrite(&t, sizeof(struct tala),1,file_locking)==0)
printf("Error opening file");
rewind(file_locking);
if (fread(&f, sizeof(struct tala),1,file_locking)==0)
printf("Error opening file");
printf("\n %d",f.rec_no);
printf("\n %ld", f.file_no);
fclose(file_locking);
}
Yes you can. Just remember to always fseek between reads and writes.
Quote the fopen man page:
Reads and writes may be intermixed on read/write streams in any order. Note that ANSI C requires that a file positioning function intervene between output and input, unless an input operation encounters end-of-file.
Extra tip: always check the return value of fopen and related functions, and handle errors (use perror or strerror to print out what failed).
Yes. The only thing to pay attention is that you have to call flush or a file positioning function before switching from output to input and call a file positioning function or be at end of file before switching from read to write.