Trying not to overwrite a file in C? - c

Hi I'm trying not to overwrite a file in C using fopen(file, "w");
My question is the file already exists as a 10 MB file but when I used the fopen the file ends up becoming 1KB. I want to write something to the file but I want it to stay the same size as well. How would I accomplish this? I saw that the "a+" appends things to the end of the file but what if I want to write something to the beginning of the file without expanding the size? It's just an empty file
Alternatively, is there a way to create a file in C with a certain size (such as 10MB)?

Yes, it is possible. By opening it with r+ you open it for 'reading and writing' (while w opens it for writing freshly).
Regarding your other question: Open a file with w and write 1000 1024 byte blocks to the file like this:
FILE *fp = fopen("file", "wb");
if(fp) {
int i = 0;
char Buf[1024];
for(; i < 1000; ++i)
fwrite(Buf, 1, 1024, fp);
fclose(fp);
}
Just once more the fopen flags for you:
r -> Opens file for reading. (File remains unchanged)
w -> Opens file for writing. (File gets erased)
a -> Opens file for appending. (File remains unchanged, file pointer gets moved to end)
Aside from these three main types, you can add a few more additional options:
b -> Opens the file as binary, ignoring formatting characters like \n
t -> Opens the file as text, specifically parsing \n as \r\n under Windows.

Open the file, then use fseek to set your position to the beginning of your file.
Edit: use r+ mode when opening. From man fopen:
r+ Open for reading and writing. The stream is positioned at
the beginning of the file.

*a way to create a file in C with a certain size (such as 10MB)?
like this:
#include <stdio.h>
int main(void){
const char *TenMBfile = "TenMB";
FILE *fp;
fp=fopen(TenMBfile, "w");
fseek(fp, 10*1024*1024-1,SEEK_SET);
fputc(0, fp);
fclose(fp);
return 0;
}

Hye! I worked on a project for adding text or 'blog' post on my web page and I found a pretty cool way to do it.
For this, I'll use a HTML file and my program.
HTML FILE:
<html>
<body>
<p> Hey this is the asssdsadasdsadas paragraph</p><br>
<p> Hey this is the asssdsadasdsadas paragraph</p><br>
</body>
</html>
C FILE:
printf("Please enter the number of bytes to write from in %s .\n", argv[0]);
int offset;
scanf("%d", &offset);
fseek(fp, -offset, SEEK_END);
strcat(argv[1], "<br>\n\n");
fprintf(fp, "%s", argv[1]);
fprintf(fp, "</body>\n</html>\n");
HTML explanation:
I start with one line defined
I put a blank line which I am going to write there.
Then I got all my ending tags.
C explanation:
I ask how many bytes I want to seek from the ending of the file wich is 17 in this case(to write to the blank line).
I get the number with scanf()
Then I seek in the file at minus x bytes because normally it's going to add bytes and we specify the whence.
Then for the purpose, here I add a break tag and also 2 newline to continue the cycle.
Then I write my wanted text.
Last, I add my 2 last tags, because when I write my text, it overwrites all after it. So after, the cursor is positioned after the last newline and I can write the ending tags.
So... This is how you can do it.

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 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.

Ansi C: Attempting to count total chars in a file

The task is simple but I am having an issue with the method returning 0.
This means my loop:
int getCharCount(FILE *fp) {
int c;
int i = 0;
while( (c = fgetc(fp)) != EOF) {
i++;
printf("Loop ran");
}
return i;
}
Did not run.
In my testing I found that the loop never runs because the "Loop ran" never prints. I am new to c and not sure if I am doing something wrong when trying to count chars in the file.
I feel like I should mention that the file is opened with "wb+" mode and that there are a few long methods that edit the file. Essentially before using this getCharCount() method the text file is cleared of all previous data, then user enters a number of 44 char length strings at a time and I use this method I just posted to calculate the total number of chars which will be used to navigate my display data method.
I am in a library working on this so if anything extra is needed to be posted or if anything needs to be clarified I will try to be quick with my responses. I don't want to post my whole code because there would be a chance to cheat and I need to get this done myself.
Thanks ahead.
If you write to the file and then call your method on the same file handle, the file handle is already at the end of the file so it will see EOF immediately. We would need to see more of the code to be sure I think.
So, you could rewind the file handle at the start of your function.
Or you could just call ftell to find out your offset in the file, which is the same as the number of bytes written if you truncate, write and do not rewind.
Why you have to read all bytes one by one to count them? It is much easier to do fseek( fp, 0, 2 ) to jump at end of file and get current position (file length) with ftell( fp ).
You are opening with the mode w+ which will truncate the file. From the fopen man page:
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 will want to open it with rb+ instead of wb+ if you are reading from a file and still want to write to it. If you have already written to it and want to read what was written, you will need to seek to the start of the file pointer.
// Both of these seek to the start
rewind(fp);
fseek(fp, 0, SEEK_SET);
If the file is not open, you could use:
off_t getFileSize(const char *filepath) {
struct stat fileStat;
stat(filepath, &fileStat);
return(fileStat.st_size);
}
If the file is open:
off_t getFileSize(int fd) {
struct stat fileStat;
fstat(fd, &fileStat);
return(fileStat.st_size);
}

How to save results of a function into text file in C

This function print the length of words with '*' called histogram.How can I save results into text file? I tried but the program does not save the results.(no errors)
void histogram(FILE *myinput)
{
FILE *ptr;
printf("\nsaving results...\n");
ptr=fopen("results1.txt","wt");
int j, n = 1, i = 0;
size_t ln;
char arr[100][10];
while(n > 0)
{
n = fscanf(myinput, "%s",arr[i]);
i++;
}
n = i;
for(i = 0; i < n - 1; i++)
{
ln=strlen(arr[i]);
fprintf(ptr,"%s \t",arr[i]);
for(j=0;j<ln;j++)
fprintf(ptr, "*");
fprintf(ptr, "\n");
}
fclose(myinput);
fclose(ptr);
}
I see two ways to take care of this issue:
Open a file in the program and write to it.
If running with command line, change the output location for standard out
$> ./histogram > outfile.txt
Using the '>' will change where standard out will write to. The issue with '>' is that it will truncate a file and then write to the file. This means that if there was any data in that file before, it is gone. Only the new data written by the program will be there.
If you need to keep the data in the file, you can change the standard out to append the file with '>>' as in the following example:
$> ./histogram >> outfile.txt
Also, there does not have to be a space between '>' and the file name. I just do that for preference. It could look like this:
$> ./histogram >outfile.txt
If your writing to a file will be a one time thing, changing standard out is probably be best way to go. If you are going to do it every time, then add it to the code.
You will need to open another FILE. You can do this in the function or pass it in like you did the file being read from.
Use 'fprintf' to write to the file:
int fprintf(FILE *restrict stream, const char *restrict format, ...);
Your program may have these lines added to write to a file:
FILE *myoutput = fopen("output.txt", "w"); // or "a" if you want to append
fprintf(myoutput, "%s \t",arr[i]);
Answer Complete
There may be some other issues as well that I will discuss now.
Your histogram function does not have a return identifier. C will set it to 'int' automatically and then say that you do not have a return value for the function. From what you have provided, I would add the 'void' before the function name.
void histogram {
The size of arr's second set of arrays may be to small. One can assume that the file you are reading from does not exceed 10 characters per token, to include the null terminator [\0] at the end of the string. This would mean that there could be at most 9 characters in a string. Else you are going to overflow the location and potentially mess your data up.
Edit
The above was written before a change to the provided code that now includes a second file and fprintf statements.
I will point to the line that opens the out file:
ptr=fopen("results1.txt","wt");
I am wondering if you mean to put "w+" where the second character is a plus symbol. According to the man page there are six possibilities:
The argument mode points to a string beginning with one of the
following sequences (possibly followed by additional characters, as
described below):
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.
As such, it appears you are attempting to open the file for reading and writing.

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