At n1256 7.19.5.2 paragraph 2 (with my bold):
If stream points to an output stream or an update stream in which the most recent
operation was not input, the fflush function causes any unwritten data for that stream
to be delivered to the host environment to be written to the file; otherwise, the behavior is
undefined.
If there was not the word 'update stream', the whole paragraph would make sense. But I don't know what it is. Standard itself doesn't introduce it. Google search doesn't seem to work. What's the meaning of it?
The term "update stream" simply means a stream that is both readable and writable.
This is specified in ยง7.19.5.3 point 3 (link, bold mine):
#include <stdio.h>
FILE *fopen(const char * restrict filename,const char * restrict mode);
[...]
The argument mode points to a string. If the string is one of the following, the file is open in the indicated mode. Otherwise, the behavior is undefined(237).
r: open text file for reading
w: truncate to zero length or create text file for writing
a: append; open or create text file for writing at end-of-file
rb: open binary file for reading
wb: truncate to zero length or create binary file for writing
ab: append; open or create binary file for writing at end-of-file
r+: open text file for update (reading and writing)
w+: truncate to zero length or create text file for update
a+: append; open or create text file for update, writing at end-of-file(237)
r+b or rb+: open binary file for update (reading and writing)
w+b or wb+: truncate to zero length or create binary file for update
a+b or ab+: append; open or create binary file for update, writing at end-of-file
(237) If the string begins with one of the above sequences, the implementation might choose to ignore the remaining characters, or it might use them to select different kinds of a file (some of which might not conform to the properties in 7.19.2).
The term "update" in this context means a file opened for both reading and writing.
The term is used in the specification of the fopen function in section 7.19.5.3 of the C99 standard:
3 The argument mode points to a string.If the string is one of the following, the file is open in the indicated
mode.Otherwise, the behavior is undefined.
r open text file for reading
w truncate to zero length or create text file for writing
a append; open or create text file for writing at end-of-file
rb open binary file for reading
wb truncate to zero length or create binary file for writing
ab append; open or create binary file for writing at end-of-file
r+ open text file for update (reading and writing)
w+ truncate to zero length or create text file for update
a+ append; open or create text file for update, writing at end-of-file
r+b or rb+ open binary file for update (reading and writing)
w+b or wb+ truncate to zero length or create binary file for update
a+b or ab+ append; open or create binary file for update, writing at end-of-file
...
6 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
Related
I wrote this code to input a number from a user and output it to a file .But its is not working ,after running the code the output.txt file is still empty.
Please tell me where I have done wrong .
I assure that I have created the output.txt file before running the program so the
file pointer will not be NULL.
#include <stdio.h>
#include <stdlib.h>
int main (void)
{
FILE *ptr;ptr=fopen("output.txt","rw");
if(ptr==NULL){printf("Error in oppening file aborting .......");exit(0);}
char ch[100];
scanf("%s",ch);
fprintf(ptr,"%s",ch);
fclose(ptr);
return 0;
}
From fopen documentation, the supported access modes are:
"r" read: Open file for input operations. The file must exist.
"w" write: Create an empty file for output operations. If a file with
the same name already exists, its contents are discarded and the file
is treated as a new empty file.
"a" append: Open file for output at the end of a file. Output
operations always write data at the end of the file, expanding it.
Repositioning operations (fseek, fsetpos, rewind) are ignored. The
file is created if it does not exist. "r+" read/update: Open a file
for update (both for input and output). The file must exist.
"w+" write/update: Create an empty file and open it for update (both
for input and output). If a file with the same name already exists its
contents are discarded and the file is treated as a new empty file.
"a+" append/update: Open a file for update (both for input and output)
with all output operations writing data at the end of the file.
Repositioning operations (fseek, fsetpos, rewind) affects the next
input operations, but output operations move the position back to the
end of file. The file is created if it does not exist.
In your code you use "rw" which is invalid and that's the reason your program doesn't work.
Change "rw" to "w" and your program will work. Note that you don't need to create output.txt, fopen will create it for you if your current user has write privileges in program's directory.
I want to open a file with c then add some content to it and close it. I just want to know a+ in fopen automatically navigates to the last character of file.
Yes it does.
Why don't you try, or read the manual ?
Here it is :
r Open text file for reading. The stream is positioned at the beginning of the file.
r+ Open for reading and writing. The stream is positioned at the beginning of the file.
w Truncate file to zero length or create text file for writing. The stream is positioned at the beginning of the
file.
w+ Open for reading and writing. The file is created if it does not exist, otherwise it is truncated. The stream is
positioned at the beginning of the file.
a Open for appending (writing at end of file). The file is created if it does not exist. The stream is positioned
at the end of the file.
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.
Well I was looking into ways to open a file in binary and I saw that you can open one for r+b and a+b but whats the difference because this is what it says for definition.
a+b :Open a file for both reading and writing in binary mode.
r+b: Open a file for both reading and writing in binary mode.
a+b
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.
r+b Open for reading and writing. The stream is positioned at the beginning of the file.
w+b Open for reading and writing. The file is created if it does not exist, otherwise it is truncated. The stream is positioned at the beginning of the file.
So, a+b will create the file if it does not exist, and it will append to the file when you write to it,
r+b will not create the file if it doesn't already exist (fopen() would fail), and writing to the file will start at the beginning of the file.
New to C and I'm trying to do a text replace in place. I thought r+ in fopen should allow me to read and write. I'm looking at every line in the file and if it begins with a / then I am prepending http://example.com to the beginning of the line. Example...line is /tree then that line becomes http://example.com/tree. The regex works fine. I can read the file fine but it is not writing. Any ideas why?
void
fix_relative (char *page)
{
FILE *fp;
fp = fopen ("file", "r+");
char line[1000];
regex_t re;
regcomp (&re, "^/", REG_EXTENDED);
while (fgets (line, sizeof line, fp) != NULL)
{
if (regexec (&re, line, 0, NULL, 0) == 0) {
fprintf (fp, "http://example.com%s\n", line);
}
}
fclose (fp);
}
No way this can possibly work. You will run into a problem as soon as your new string is not exactly as long as the original string. In addition, since you are working in text mode, there may be additional artefacts because of newline/carriage return translation.
Instead, do the following:
open the file "file" for reading only
create a new temporary file for writing only
read a line, modify if necessary, write to new file
when done, delete "file" and rename your temp file.
This may help you to understand your problem
fopen function
Purpose:
Opens a stream. The safer fopen_s function is also available.
Syntax:
FILE * fopen(const char *name, const char *mode);
Declared in:
The fopen function opens the file whose name is the string pointed to by name, and associates a stream with it. The string may contain a full path (from the root), a relative path (from the current directory) or just a name.
The argument mode points to a string. If the string is one of the following, the file is open in the indicated mode.
"r" Open text file for reading.
"w" Truncate to zero length or create text file for writing.
"a" Append; open or create text file for writing at end-of-file.
"rb" Open binary file for reading.
"wb" Truncate to zero length or create binary file for writing.
"ab" Append; open or create binary file for writing at end-of-file.
"r+" Open text file for update (reading and writing).
"w+" Truncate to zero length or create text file for update.
"a+" Append; open or create text file for update, writing at end-of-file.
"rb+" Open binary file for update (reading and writing).
"wb+" Truncate to zero length or create binary file for update.
"ab+" Append; open or create binary file for update, writing at end-of-file.
"r+b" Same as "rb+"
"w+b" Same as "wb+"
"a+b" Same as "ab+"
Opening a file with read mode ('r' as the first character in the mode argument) fails if the file does not exist or cannot be read.
Opening a file with append mode ('a' as the first character in the mode argument) causes all subsequent writes to the file to be forced to the then current end-of-file, regardless of intervening calls to the fseek function.
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, 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.
When opened, a stream is fully buffered if and only of it can be determined not to refer to an interactive device. The error and end-of-file indicators for the stream are cleared.
Returns:
A pointer to the object controlling the stream on success, otherwise a null pointer.
One thing that may not be clear: if you update lines in the file, and your replacement text is not precisely the same length as what it is replacing, you will make a complete hash of the file: you will be overwriting what comes after it.
So, if you have a file that contains the sentences:
I love programming.
I love life.
and you set the file position to the first sentence and replace "love" with "loathe", you will NOT get
I loathe programming
I love life
You will get
I loathe programming love life
because you have now overwritten the line separator from the first sentence, and the "I" from the next sentence.
If you replace a string with a longer string, that will push every other character in the file forward. To do that replacement, you'd have to read the entire file into memory, do your replacements, and then write the file back out to disk.
Very simply put, I have the following code snippet:
FILE* test = fopen("C:\\core.u", "w");
printf("Filepointer at: %d\n", ftell(test));
fwrite(data, size, 1, test);
printf("Written: %d bytes.\n", size);
fseek(test, 0, SEEK_END);
printf("Filepointer is now at %d.\n", ftell(test));
fclose(test);
and it outputs:
Filepointer at: 0
Written: 73105 bytes.
Filepointer is now at 74160.
Why is that? Why does the number of bytes written not match the file pointer?
Since you're opening the file in text mode, it will convert end-of-line markers, such as LF, into CR/LF.
This is likely if you're running on Windows (and you probably are, given that your file name starts with "c:\").
If you open the file in "wb" mode, I suspect you'll find the numbers are identical:
FILE* test = fopen("C:\\core.u", "wb");
The C99 standard has this to say in 7.19.5.3 The fopen function:
The argument mode points to a string. If the string is one of the following, the file is
open in the indicated mode. Otherwise, the behaviour is undefined.
r open text file for reading
w truncate to zero length or create text file for writing
a append; open or create text file for writing at end-of-file
rb open binary file for reading
wb truncate to zero length or create binary file for writing
ab append; open or create binary file for writing at end-of-file
r+ open text file for update (reading and writing)
w+ truncate to zero length or create text file for update
a+ append; open or create text file for update, writing at end-of-file
r+b or rb+ open binary file for update (reading and writing)
w+b or wb+ truncate to zero length or create binary file for update
a+b or ab+ append; open or create binary file for update, writing at end-of-file
You can see they distinguish between w and wb. I don't believe an implementation is required to treat the two differently but it's usually safer to use binary mode for binary data.
what does fwrite return? normally the return value should be the number of bytes written.
Also, what does the ftell() answer with right before the fseek?
It might help to know what operating system, C compiler version and C library.
A filepointer is a cookie. It has no value. The only thing you can use it for is to seek to the same place in a file. I'm not even sure if ISO C guarantees that ftell returns increasing values. If you don't believe this, please look at the different seek() modes. They exist precisely because the position is not a simple byte offset.
windows doesn't actually write all data out to the file without a flush and possibly an fsync. Maybe that's why