Duplicating file pointers? - c

Just a quick question: Is there a way to duplicate a file pointer (those returned by fopen()), similar to how dup() duplicates a file handlers returned by functions like open()?
Basically, I want to be able to do something like this:
FILE *fp = fopen("some_file", "r");
FILE *fp2 = /* do something to duplicate the file pointer */;
fclose(fp); // fp2 is still open
/* do something with fp2 */
fclose(fp2);

FILE *fp2 = fdopen (dup (fileno (fp)), "r");

You could use fileno to get a descriptor for a FILE*, dup that, and then use fdopen to get a new FILE* from the new descriptor.

I opened twice the same file and assigned two pointers and in the end closed both separately. In my case I had to show the content in a text window using one pointer and process the data in file using the other pointer.
e.g.
//define global variables
FILE *fp1 = fopen("some_file", "r");
//fp1 used in functioncall to display textbuffer
fclose(fp1);
//fp2 used in functioncall to process data
fclose(fp2);

Related

how do I open files using an array in c

I want to open file named ex1, ex2, ex3 ...exn etc.
Now when i put the value of n like, n=1, ex1 will be opened
for, n=2, ex2 file will be opened and then I will read or write my c program output array from or into it.
can the name of the file be given as a string?
As I am new with programing please help me to solve this problem.
Normally when you open a file you use the function fopen
fp = fopen ("file.txt", "w+");
if (fp == NULL)
{
exit(1); // Or you can raise some error code and return if this code is in a function.
}
// Process the file
Now in your case, you need to manipulate the filename. So you can take a C string for this.
char filename[10];
// N is set from code above
sprintf(filename,"ex%d",N);
fp = fopen (filename, "w+");
// Further behaviour is same

Check if a file is empty or not

How can I check if a text file has something written or not. I tried:
LOGIC checkfile(char * filename)
{
FILE *pf;
pf=fopen(filename,"wt");
fseek(pf,0,SEEK_END);
if(ftell(pf)==0)
printf("empty");
}
This function returns empty everytime, even in my text file I have few words or numbers written.
The problem is that you opened the file for writing. When you do that, everything in the file is lost, and the length of the file is truncated to 0.
So you need to open the file for reading. And the easiest way to see if the file is empty is to try to read the first character with fgetc. If fgetc returns EOF, then the file is empty.
First of all: DO NOT OPEN THE FILE FOR WRITING!
second: for knowing about file status in C you can use fstat which is in sys headear file!
You can use struct stat for using this function
here is a simple example:
#include <sys/stat.h>
int main(void)
{
int fields = 0;
int size = 0;
// Open the file test.txt through open()
// Note that since the call to open directly gives
// integer file descriptor so we used open here.
// One can also use fopen() that returns FILE*
// object. Use fileno() in that case to convert
// FILE* object into the integer file descriptor
if(fields = open(file_path, "r")){
struct stat buf;
fstat(fields, &buf);
size = (int)buf.st_size;
}
printf("size of file is %d", size);
return 0;
}
Note: I just include a header file that related to fstat. You can add other header files yourself
What about using fscanf to read the file, and check if something was actually read?
FILE *fp;
char buff[255] = "";
fp = fopen(filename, "r");
fscanf(fp, "%s", buff);
if (!*buff)
printf("Empty\n");
else
printf("%s\n", buff);
fclose(fp);

FILE I/O showing Compile Error in C

I am trying to write a character to a file in C, but this code:
case 4: //If the user types 4 (reset)
FILE * fp;
FILE *fp;
fp = fopen("settings.txt", "w");
fprintf(fp, "a");
int fclose(FILE * fp);
break;
shows this error:
fileio.c:72:5: error: expected expression
FILE * fp;
(Yes, I know I used file * fp two times, but without both, it shows even more errors.)
How can I fix this?
There's a few issues going on here. You can't declare new variables in a case statement. Declare your fp outside the switch. Also, only declare it once, and when you close it, call the function instead of writing a new function prototype:
fclose(fp);
There are several issues with this code. The main one you are facing is that you cannot declare variables directly under a case statement. If you need to declare variables there, you must enclose the code block in curlies, thus:
case 4: //If the user types 4 (reset)
{
FILE *fp;
fp = fopen("settings.txt", "w");
fprintf(fp, "a");
fclose(fp);
break;
}
Note that I also fixed your fclose() call--what you had was incorrect.
In the close statement you define a new pointer again. Try just
FILE *fp;
fp = fopen("settings.txt", "w");
fprintf(fp, "a");
fclose(fp);

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.

Does fseek() move the file pointer to the beginning of the file if it was opened in "a+b" mode?

I wish to open a file using the "a+b" mode, i.e. if it does not exist it is created automatically, but if it does I don't want to overwrite it. I want to be able to read and write to the file.
The file is binary, and I want to save records of a specific struct in it. So I want to do fseek() to the record I want and then save the record using fwrite().
The code looks as follows (MyRecord is a typedef to a struct, while FILENAME is a #define to the file's name):
int saveRecord(MyRecord *pRecord, int pos)
{
FILE* file = fopen(FILENAME, "a+b");
if (file == NULL)
{
printf("Unable to open file %s\n", FILENAME);
return 0;
}
fseek(file, pos * sizeof(MyRecord), SEEK_SET);
fwrite(pRecord, sizeof(MyRecord), 1, file);
fclose(file);
return 1;
}
However this code just appends the record to the end of the file, even if I set pos to 0. Why isn't fseek() with SEEK_SET working in append mode?
I know I can simply open it with "r+b" and if it fails open it with "wb", but I want to know why this doesn't work and why fseek() with SEEK_SET is leaving the file pointer at the end. Any references to places where this behaviour is documented appreciated (because I couldn't find any, or I am using the wrong keywords).
That's because in a mode, writing to the FILE* always appends to the end. fseek only sets the read pointer in this mode. This is documented in the C standard, 7.19.5.3 fopen:
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.
Plain C does not have any sane way to achieve what you want. If you're on a POSIX system or anything remotely close, you can use fd=open(FILENAME, O_CREAT|O_RDRW, 0666) and then fdopen(fd, "rb+").
Edit: Another thing you could try, with plain C:
f = fopen(FILENAME, "a+b");
if (!f) /* ... */
tmp = freopen(0, "r+b", f);
if (tmp) f = tmp;
else /* ... */
Use "r+b" mode and fallback to "w+b" if it fails.
The "a+b" mode, allows you to read and append; the "r+b" allows random read and write.
The documentation for fopen describes how the file behaves with the different modes.

Resources