Removing and renaming files with C error - c

So i'm trying updating data from original file to a new temporary file, then i remove the original file and rename the temp file with the name of the original one like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int main(){
FILE * fptr = NULL;
FILE * temp;
fptr = fopen("Original.txt", "rw+");
temp = fopen("temp.txt", "w");
if(fptr==NULL)//Check if file was opened successfully
{
printf("File could not be opened");
}
//cicle of me adding data to temp file
fclose(fptr);
fclose(temp);
remove("Original.txt");
rename("temp.txt","Original.txt");
return 0;
}
it works the first time, but when i execute again the Original.txt ends up blank. What can be causing that?
I've tried changing temp = fopen("temp.txt", "w"); to temp = fopen("temp.txt", "ab+"); but the info of Original.txt ends up with no spaces or new lines between (all together). And same with "wb"
"rb" the Original.txt file disappears.
if necessary ill add the entire code, althought i dont think its revelant

The moment you do an fopen (path, "w") it truncates the file pointed by the path. Then you close the file. Therefore essentially, your "temp.txt" is an empty file after the line fclose (temp). Get rid of the "w+" and "w" as they will truncate the file (make it zero length).
See man fopen
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.
You do not need to open and or close the file at all. If you see the remove and rename uses absolutely nothing from the previous part of the code. Also check man rename and man remove. If you want to know if the files are present of not. Check the return values of these functions. In case of error, you can always inspect the errno to understand what exactly went wrong. (See manpage for details).

Not sure what you are trying to do exactly, but depending on your question, you need only "r" mode for reading.
i.e, fptr = fopen("Original.txt", "r");
Additionally, couple of suggestions, but not answer to your question:
You are checking fptr == NULL, but proceeding to write data anyway? what if fptr == NULL is true and you try to read from a NULL pointer? Besides putting an error message, put a return -1 or something so that the program does not continue further for that case.
You should check temp == NULL as well, to detect whether file is opened for writing also. What if temp == NULL is true and you try to write to a NULL pointer?

Related

How to read from a file using fgets?

I'm trying to read the contents of "Danfilez.txt" using fgets. However on completion the program returns a random value and i'm unsure why. I'm new to programming so any help would be greatly appreciated!
int main()
{
FILE* Danfile = fopen ("Danfilez.txt", "w");
char fileinfo [50];// Character arrays for file data //
if (Danfile == NULL)
{
printf ("ERROR\n");
}
else
{
printf("Everything works!\n");
fprintf (Danfile, "Welcome to Dan's file.");
fgets(fileinfo,50,Danfile);
printf("%s\n",fileinfo);
fclose (Danfile); // CLOSES FILE //
}
return 0;
}
Since you're both reading and writing from the file you want to use "w+" to open the file rather than just "w".
But that won't fix things because once you've written out that text, your position in the file is still at the end, so you'll also need to reset the position before you can read anything in using fseek()
fseek(Danfile,0,SEEK_SET);
While using fopen() you pass the option for opening as an argument to the funtion. Here is the list:
"r" - Opens the file for reading. The file must exist.
"w" - Creates an empty file for writing. If a file with the same name already exists,
its content is erased and the file is considered as a new empty file.
"a" - Appends to a file. Writing operations, append data at the end of the
file. The file is created if it does not exist.
"r+" - Opens a file to update both reading and writing. The file must exist.
"w+" - Creates an empty file for both reading and writing.
"a+" - Opens a file for reading and appending.
Try using "r+" or "w+". After writing some text, your position in the file will move forward along with the text. Use rewind(FILE* filename) to move your position straight to the start of the file. For more information related to file handling i recommend checking what is inside stdio library:
https://www.tutorialspoint.com/c_standard_library/stdio_h.htm

Reading from file in C using fread

I'm learning how to read content from a file in C. And I manage to scrape through the following code.
#include <stdio.h>
#include <stdlib.h>
void read_content(FILE *file) {
char *x = malloc(20);
// read first 20 char
int read = fread(x,sizeof(char),20,file);
if (read != 20) {
printf("Read could not happen\n");
}
else {
printf("the content read is %s",x);
}
free(x);
return;
}
int main(int argc,char *argv[]) {
FILE *fp;
fp = fopen("test.txt","w+");
read_content(fp);
fclose(fp);
return 0;
}
But for some reason (which I'm not able to understand) I see the read bytes count as 0.
The problem is that you open the file with the w+ mode. There are two possibilities:
if the file doesn't exist, it will be created empty. Reading from it immediately gives end of file resulting in fread() returning 0.
if the file does exist, it will be truncated i.e. changed into an empty file. Reading from it immediately gives end of file resulting in fread() returning 0.
If you just want to read from the file (as per your example), open it in mode r. If you want to read and write without destroying its existing content, use mode r+.
Whatever mode you choose, always check that fopen() returns non null and print the error if it returns null (this is not the cause of your problem but is best practice).
From Man Page w+ flag:
Open for reading and writing. The file is created if it does
not exist, otherwise it is truncated.
You are probably trying to open a file which doesn't exist at the path you provided, or is read-only as #WhozCraig suggested in comment. This means a new file is being created, an empty file! hence you are seeing 0 bytes read.
To sum up, The fopen is failing, in that case you need to check the return value if it is equal to -1.
To find what was the error, you can check the errno as it is set to
indicate the error.
If you are only intending to read, open the file with r flag instead of w+
The problem lies within this line of code:
fp = fopen("test.txt","w+")
the "w+" mode, clear the previous content of the file and the file will be empty when you just going to read the file without writing anything to it. Hence, it is printing "Read could not happen" because you are trying to read an empty file.
I would suggest you to use "r+" mode, if you are willing to read and then write into the file. Otherwise, r mode is good enough for simple reading of a file.

Reading a File in C: different behavior for "r" and "a+" flags

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, &current_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.

Having problems with fseek() in C

So, I have this function on my program that is supposed to save a "car_str" structure into the desired place on a file specified as a parameter. But when I run it, it keeps overwriting the first slot again and again, as if fseek didn't point to the specified place on the file. Is there any problem with my code? I think it may be related with the multiplication, since without it the program does well, but I cannot point to the place I want.
void save(int car_nbr)
{
FILE *f;
f = fopen("memory.txt","wb");
if (!f)
{
printf ("error");
}
else
{
car_nbr--;
fseek(f, sizeof(struct car_str)*car_nbr, SEEK_SET);
fwrite(&car,sizeof(struct car_str),1,f);
rewind(f);
fclose(f);
printf("\nsaved");
}
}
you need to fopen with r+b.
if you fail than file not exist, so you can try use "wb"
"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.
"r+" - read/update: Open a file for update (both for input and output). The file must exist.
f = fopen("memory.txt","r+b");

C - fwrite() not outputting to file

Never used fwrite(), so I'm not sure exactly what I'm doing wrong. I'm just testing it now and all I want to do is try to write a single char out to a file until it reaches the end. The file I'm writing to is one I downloaded from my teacher's website. When I check the properties of it, the type is only listed as "file". It's supposed to just be an empty 2MB file for us to write our code to (file system lab if anyone's wondering). Here's my code:
#include <stdio.h>
#include <string.h>
int main()
{
char c;
FILE *fp;
char testing[2] = {'c'};
fp = fopen("Drive2MB", "rw");
fseek(fp, 0, SEEK_SET); //make sure pointers at beginning of file
while((c=fgetc(fp))!=EOF)
{
fwrite(testing, 1, sizeof(testing), fp);
fseek(fp, 1, SEEK_CUR); //increment pointer 1 byte
}
fclose(fp);
}
When I run this, an error message pops up saying "Debug Assertion Failed!...Expression:("Invalid file open mode",0) and prints "The program '[3896] filesystem.exe: Native' has exited with code 3 (0x3)."
You have opened the file for reading (that's what the r stands for in fopen("Drive2MB", "r");). You may not write to a file opened for reading.
You're opening it in read only mode
Use r+ for the fopen
fp = fopen("Drive2MB", "r")
your openning your file in read only
try
fp = fopen("Drive2MB", "r+");
You've opened the file for reading with the "r" part of fopen. To write to the file, you can open it in read/write mode or write mode.
// Read/write mode
fp = fopen("Drive2MB", "r+");
// Write only mode
fp = fopen("Drive2MB", "w");
I never like to use "rw" personally. When you open a file, it really should have one reason to be opened. You also do not need to call fseek to move to the start of the file and you do not need to use fseek to advance the file pointer. fopen will automatically open it to the start of the file and fwrite will automatically advance the pointer. fseek should only be used if you are "seek"ing inside of the file to get to a specific point.
In the case you've given, you would only need write ("w") mode since you are not ever reading from the file.
Use fopen r+ or w+ to open the file.
Use fflush to flush data to disk after fwrite is complete.
Use ferror to check if there is any problem with the file stream after fwrite is complete.
Check whether the disk has enough free space.
I solved the problem with 3, 4.

Resources