C - Using fgetc on a write file - c

Say we have a file pointer like this:
FILE *output = fopen("test.out", "w");
After writing to it, I want to read it using fgetc
However when I do:
char c1 = fgetc(output);
and then I print out c1 I get that c1 equals -1 which means there was an error in fgetc. Is it because I opened the file using "w"?
How can I read and write from the same file in the same function?

If you want to be able to both read and write the file, you should open it in write/update mode (ie pass “w+” to the mode argument instead of just “w”)
Also be sure to do a frewind() or fseek() before trying to read from the file, otherwise you’ll be trying to read past the end of the file’s data.

You can't read from a write-only file. Open the file for read/write access using "w+" instead.
Also, after you write to the file, you have to seek backwards with fseek() before you can then read what you previously wrote.

Related

Reading a string from a file with C. Fopen with w+ mode is not working

I made a C program that reads a string from a .txt file, then it encrypts the string, and finally it writes the string in the same file.
The thing is that if I use fopen("D:\\Prueba.txt","w+"), the program doesn't work, it prints garbage like this )PHI N.
I've debugged and I know the error is there in that line, because if I use fopen("D:\\Prueba.txt","r+"), the program works, and it writes what it should.
But I want to use w+ because it will rewrite what the .txt file had. Why is w+ not working?
If you're opening with w+ to first read the content, that's not going to work. From C11:
w+: truncate to zero length or create text file for update.
What's probably happening is that you read data from the now empty file but don't correctly check that it worked. That would explain the weird "content" you see of )PHI N.
One solution is to open the file as with r, open another file with w, and transfer the contents, encrypting them as part of that process. Then close both, delete the original, and rename the new one to the original name. This will allow you to process arbitrarily-sized files since you process them a bit at a time.
If you don't want to use a temporary file, and you're sure you can store the entire content in memory, you could open it r+, get the content, the reopen it with a new mode, such as with:
FILE *readFh = fopen( "myfile.txt", "r+");
// Read in content, massage as needed.
FILE *writeFh = frepoen( NULL, "w+", readFh);
// Provided that worked, you should now have an empty file to write to.
// Write back your massaged data.

Reading from a file opened using append mode

It might be a very dumb question but I am modifying someone else's code and it seems I need to read from a file that was opened in append mode. I tried to fseek to the beginning of the file but nothing is being read.
I know I can change the mode to rw but I wanted to know why fseek is not working. In the man page it does say write ignores fseek but nothing about read though.
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.
When you open in append mode, the file pointer is returned to the end of file before every write. You can reposition the pointer with fseek for reading, but as soon as you call a function that writes to the file, the pointer goes back to the end of file.
The answer at Does fseek() move the file pointer to the beginning of the file if it was opened in "a+b" mode? references the appropriate section of the C standard.
Use the "w+" mode if you would like to write to arbitrary places in file. An existing file will be overwritten.
If you would like to append to an existing file initially, but then fseek to arbitrary place, use "r+" followed by
fseek(f, 0, SEEK_END)
Hope it helps..

Opening a file in 'a+ 'mode

If a file is opened using the following command:
FILE *f1=fopen("test.dat","a+");
The man page reads:
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.
So does f1 have 2 separate offset pointers, one for read & another for write?
No.
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.
No it has only one pointer.
You can never mix reading and writing operations on a FILE without calling fseek in between. It may work as you wish on some implementations, but a program that depends on this has undefined behavior. Thus the questions of having 2 positions is meaningless.

Inserting data to file in c

I need to add a string before the 45th byte in an existing file. I tried using fseek as shown below.
int main()
{
FILE *fp;
char str[] = "test";
fp = fopen(FILEPATH,"a");
fseek(fp,-45, SEEK_END);
fprintf(fp,"%s",str);
fclose(fp);
return(0);
}
I expected that this code will add "test" before the 45th char from EOF, instead, it just appends "test" to the EOF.
Please help me to find the solution.
This is continuation of my previous question
Append item to a file before last line in c
Open it with mode r+ (if it already exists) or a+ (if it doesn't exist and you want to create it). Since you're seeking to 45 bytes before the end of file, I'm assuming it already exists.
fp = fopen(FILEPATH,"r+");
The rest of your code is fine. Also note that this will not insert the text, but will overwrite whatever is currently at that position in the file.
ie, if your file looks like this:
xxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxx
Then after running this code, it will look like this:
xxxxxxxtestxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxx
If you really want to insert and not overwrite, then you need to read all the text from SEEK_END-45 to EOF into memory, write test and then write the text back
Don't open it as append (a) if you plan to write at arbitrary positions; it will force all writes to the end of the file. You can use r+ to read or write anywhere.
To avoid platform-specific configurations, always explicitely indicate the binary or text mode in your fopen() call.
This will save you hours of desperations if you port your code one day.

How do I overwrite X bytes on offset Y with fwrite()?

All I can find using fopen() and fwrite() in C is to delete all contents and start writing again or append to the end of the file. What if I need to go to some offset in the file and overwrite a few bytes?
Is that possible with some function?
You can open the file with the "rb+" option and then use fseek with SEEK_SET to go to a specific location. Therb+ opens it for both reading and writing as a binary file (the file must exist in order for it to succeed - it will not create a new file).

Resources