I'm writing a program that asks the user for a file name, and creates it if it doesn't exist. At the end of the program, I want to check if the created program is empty, and if it is, delete it. Not deleting it and then running the program with that same file name messes up the way the input is detected.
I've tried using rewind() to go back to the beginning and then checking feof() to see if the beginning of the file was the EOF character, but that didn't work.
Then, I did some searching online, and found a method that used fseek() to go to the end of the file, and then checked with ftell() whether the end of the file was at position 0, but again this did not work.
I went back and did more poking around, and found that the problem might be because I hadn't used fclose() first, so I tried the previous two attempted solutions again, this time being sure to close the file before trying to delete it. Still no dice.
I tried checking what errno was set to, and got 2: No such file or directory. This is patently false, since if that was the case, it would mean that I had accomplished my goal, and when I check the working directory, the file is still there.
I have absolutely no idea what to try next. Can anyone point me in the right direction?
Here are the ways I've tried to delete the file (fp is the file pointer, and file is a char pointer with the name of the file that fp points to.) :
Attempt 1:
rewind(fp);
if(feof(fp)){
remove(file);
}
Attempt 2:
fseek(fp, 1, SEEK_END);
long size = ftell(fp);
if(size == 0){
remove(file);
}
Attempt 3:
fseek(fp, 1, SEEK_END);
long size = ftell(fp);
fclose(fp);
if(size == 0){
remove(file);
}
Attempt 4:
rewind(fp);
int empty = 0;
if(feof(fp)){
empty = 1;
}
fclose(fp);
if(empty == 1){
remove(file);
}
UPDATE: Here's a couple MCVEs, one for each method.
#include <stdio.h>
#include <errno.h>
int main() {
FILE *fp;
char file[40];
scanf(" %[^\n]s", file);
fp = fopen(file, "r");
if(fp == NULL){
fp = fopen(file, "w");
int result;
rewind(fp);
int empty = 0;
if(feof(fp)){
empty = 1;
}
fclose(fp);
if(empty == 1){
result = remove(file);
}
printf("%d\n", result);
printf("%d\n", errno);
return 0;
}
Version 2:
#include <stdio.h>
#include <errno.h>
int main() {
FILE *fp;
char file[40];
scanf(" %[^\n]s", file);
fp = fopen(file, "r");
if(fp == NULL){
fp = fopen(file, "w");
int result;
fseek(fp, 1, SEEK_END);
long size = ftell(fp);
fclose(fp);
if(size == 0){
result = remove(file);
}
printf("%d\n", result);
printf("%d\n", errno);
return 0;
}
UPDATE 2:
I just realized that when I was making the MCVEs, when I ran them, result was returning 0, which should have meant that it was successful, but the file was still there in the directory. I'm at a loss for words.
The code wasn't reaching the remove statement.
Related
Okay, so I have tried to read a whole file with fread(), and I can do it successfully, but the longer the file, the more the excess characters I get on the output.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main() {
FILE* fpointer = fopen("test.txt", "r");
char* wholeFile;
long int fileSize;
if (fpointer == NULL) return 0;
fseek(fpointer, 0, SEEK_END);
fileSize = ftell(fpointer);
rewind(fpointer);
printf("fileSize == %ld\n", fileSize);
wholeFile = (char*)malloc(fileSize+1, sizeof(char));
if (wholeFile == NULL) return 1;
fread(wholeFile, sizeof(char), fileSize, fpointer);
fclose(fpointer);
wholeFile[fileSize] = '\0';
printf("This is whole file:\n\n%s", wholeFile);
free(wholeFile);
return 0;
}
If the file looks like this:
This is cool file.
I get this as output:
This is cool file.²²²²
And if the file is like this:
This
is
cool
file.
I get this as the output:
This
is
cool
file.═══²²²²
Any idea where I'm wrong?
EDIT: Edited code according to comments.
You need to allocate one more than the size of the file and set the last position in the buffer to 0.
C expects character arrays to be null terminated.
Use "rb" to open the file in binary mode. This will ensure you get a reliable count of bytes in the file from Windows.
FILE* fpointer = fopen("test.txt", "rb");
wholeFile = (char*)malloc(fileSize + 1);
wholeFile[fileSize] = '\0';
I am trying to swap the existing characters from the file with new characters one by one. The new characters are obtained by manipulating the existing characters by subtracting one from the ASCII code. The file already exists with text, but I ended up getting an infinite loop for some reason. What am I doing wrong?
#include <stdio.h>
int main()
{
FILE *fp = fopen("myfile.txt", "r+");
if (fp == NULL)
printf("File cannot be opened.");
else
{
// Used for retrieving a character from file
int c;
// Pointer will automatically be incremented by one after executing fgetc function
while ((c = fgetc(fp)) != EOF)
{
// Decrement pointer by one to overwrite existing character
fseek(fp, ftell(fp)-1, SEEK_SET);
// Pointer should automatically increment by one after executing fputc function
fputc(c-1, fp);
printf("%c\n", c);
}
fclose(fp);
}
return 0;
}
-EDIT-
I changed datatype of c from char to int, but problem still persisted. However, my problem has been resolved by adding fseek(fp, 0, SEEK_CUR) after fputc() call. I believe Jonathan Leffler's comment should become an answer since this kind of problem was not answered from the other question.
try this
#include <stdio.h>
int main(void){
FILE *fp = fopen("myfile.txt", "r+");
if (fp == NULL) {
printf("File cannot be opened.");
return -1;
}
int c;
long pos = ftell(fp);
while ((c = fgetc(fp)) != EOF){
fseek(fp, pos, SEEK_SET);//In the case of text file Do not operate the offset.
fputc(c-1, fp);
fflush(fp);//To save the output.
pos = ftell(fp);
printf("%c\n", c);
}
fclose(fp);
return 0;
}
I am learning to program in C. Please explain why my program doesn't work. What is wrong? The program creates a file, writes a number into this file, and increases this number each time I run this program. The program counts how many times I have opened the file.
#include <stdio.h>
int main (void)
{
int n;
int c;
FILE* f = fopen("count_pr.bin", "a+");
if ((c=fgetc(f)) == EOF)
{
n=1;
fputc(n, f);
}
else
{
++n;
fseek(f, 0, SEEK_SET);
fputc(n, f);
}
printf ("The program was opened: %d\n", n);
fclose(f);
}
In the "a+" mode, from here
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.
Output operations move the position back to the end of the file. So every write you do will be at the end of the file.
In addition, you need to make changes as suggested by Klas
If you want to overwrite the number each time, you should use r+ mode
read/update: Open a file for update (both for input and output). The file must exist.
There is still the issue of creating the file if it does not exist, so in that case, if the file cannot be opened in r+ mode, then you can open it in "w" or "w+" mode and only write to it.
I have updated the code below.
#include <stdio.h>
int main (void)
{
int n;
int c;
FILE* f = fopen("count_pr.bin", "r+");
if (f == NULL)
{
f = fopen("count_pr.bin", "w");
if (f != NULL)
{
n = 1;
fputc(n, f);
}
else
{
printf (" File Open Error");
exit(1);
}
}
else
{
c=fgetc(f);
n = c+1;
fseek(f, 0, SEEK_SET);
fputc(n, f);
}
printf ("The program was opened: %d\n", n);
fclose(f);
}
You read the value into c. Then you increase the uninitialized variable n by one and write n to the file. Since n is uninitialized you invoke undefined behaviour.
You need to use the value you read:
else
{
n = c + 1; // Changed line
fseek(f, 0, SEEK_SET);
fputc(n, f);
}
I'm new to programming in C, doing some work on a MIDI recording program that plays back the notes, and can't seem to get the program to read from the file into my structure array.
Here's the structure:
typedef struct
{
int noteNumber;
int vel;
int oscillatorNumber;
float freq;
} oneNote;
And here's the code to read the notes in:
oneNote notes[2000];
for (count = 0; count < fileSize; count++)
{
fscanf(filePointer, "%d %d %d\n", ¬es[count].noteNumber,
¬es[count].vel,
¬es[count].oscillatorNumber);
notes[count].freq = ntof(notes[count].noteNumber);
}
Code where file is opened:
filePointer = fopen("noteRecordFile.txt", "r");
if (filePointer == NULL)
{
printf("Error opening file\n");
}
else
{
printf("File opened\n");
fseek(filePointer, 0L, SEEK_END);
fileSize = ftell(filePointer);
}
Just doesn't store the and of the data in the structure, as can be seen here:
Image of debug console
First few lines of noteRecordFile.txt:
48 108 0
50 108 0
52 100 0
There are several issues:
Remove following 2 lines, because it puts the file pointer to the end of the file and we want to start the reading at the start of the file, and ftell will give you the number of bytes in the file and not the number of lines.
fseek(filePointer, 0L, SEEK_END);
fileSize = ftell(filePointer);
Then you need this:
FILE *filePointer = fopen("noteRecordFile.txt", "r");
if (filePointer == NULL)
{
printf("Error opening file\n");
exit(1); // <<< abort program if file could not be opened
}
else
{
printf("File opened\n");
}
int count = 0;
do
{
fscanf(filePointer, "%d %d %d", ¬es[count].noteNumber,
¬es[count].vel,
¬es[count].oscillatorNumber);
notes[count].freq = ntof(notes[count].noteNumber);
count++;
}
while (!feof(filePointer)); // <<< read until end of file is reached
...
We cannot know the number of lines the file contains without reading the whole file, so we use a different approach: we just read until the end of the file is reached.
You still need to add a check, because if the file contains more than 2000 lines, you will run into trouble. This is left as an exercise to the reader.
It won't because you reached the end of the file on the line:
fseek(filePointer, 0L, SEEK_END);
you need to reset the file pointer to the beginning of the file:
fseek(filePointer, 0L, SEEK_SET)
Are you sure about your file format ?
As i see, you read the header too as a normal data line...
Try reading this, maybe it'll help you.
MIDI
You can try openning the file as binary, i remember it fixed an issue i had on some sound files...!
Do you have any error/warning during compilation and execution ?
I'm writing a wrapper to help me in my future projects (I finished C book), and want to copy a file without using fgetc. Here's my code, it doesn't work:
int CopyFile(char* filename, char* dest)
{
FILE* fp, *fout;
fp = fopen(filename,"rb");
//fout = fopen(dest, "wb");
if(fp == NULL)
{
return -1;
}
/*while((c = fgetc(fp)) != EOF)
{
fputc(c,fout);
}*/
long size = GetFileSize(fp);
printf("%lu", size);
char* file = malloc(size);
fread(file, size, 1, fp);
//fclose(fp);
fout = fopen(dest, "wb");
fwrite(file, size, 1, fout);
fclose(fp);
fclose(fout);
return 0;
}
I even open the files with a hexeditor and they aren't similar. What am I doing wrong?
The problem is in the GetFileSize function, where you move the file-pointer to the end, but you never rewind to the beginning again.
That means your fread function call will not actually read anything, as the pointer already is at the end of the file. So what's written is the contents of the allocated memory, which is indeterminate (and will be seemingly random).
If you checked what fread returned, you would have seen this immediately.
Let this be a lesson on always checking the return values of functions which can fail in one way or the other.