I am new to the C programming language. I am learning file I/O, and am confused with the fseek function. Here is my code
#include <stdio.h>
#include <stdlib.h>
struct threeNumbers {
int n1,n2,n3;
}
int main (){
int n;
struct threeNumbers number;
FILE *filePointer;
if ((filePointer=fopen("\\\\wsl$\\Ubuntu-20.04\\home\\haseeb\\learningC\\file Input and Output\\program2\\program.bin","rb"))==NULL){
printf("error! opening file);
/* if pointer is null, the program will exit */
exit(1);
}
/* moves the cursore at the end of the file*/
fseek(filePointer,-sizeof(struct threeNumbers),SEEK_END);
for(n=1;n<5;++n){
fread(&number,sizeof(struct threeNumbers),1,filePointer);
printf (" n1:%i\tn2:%i\tn3:",number.n1,number.n2,number.n3);
fseek(filePointer,-2*sizeof(struct threeNumbers),SEEK_CUR);
}
fclose(filePointer);
return 0;
}
I know that this program will start reading the records from the file program.bin in the reverse order (last to first) and prints it.
my confusion is I know that "fseek(filePointer,-sizeof(struct threeNumbers),SEEK_END);" will move the cursor at the end of the binary file. What does "fseek(filePointer,-2*sizeof(struct threeNumbers),SEEK_CUR);" do? I think it moves to the current location, but what is the point of the cursor cumming to the current location in this program? Also why is it -2 instead of being just "-sizeof(struct threeNumbers)"?
Disregarding the actual code, this is what fseek() does:
The fseek() function sets the file position indicator for the stream
pointed to by stream. The new position, measured in bytes, is obtained
by adding offset bytes to the position specified by whence. If whence
is set to SEEK_SET, SEEK_CUR, or SEEK_END, the offset is relative to
the start of the file, the current position indicator, or end-of-file,
respectively. A successful call to the fseek() function clears the
end-of-file indicator for the stream and undoes any effects of the
ungetc(3) function on the same stream.
fseek(filePointer,-sizeof(struct threeNumbers),SEEK_END) will not "move the cursor at the end of the binary file"; it will move it sizeof(struct threeNumbers) before the end of the file.
Related
I have seen programs for file handling and in one of the program using fseek as shown below:
/* This example opens a file myfile.dat for reading.
After performing input operations (not shown), it moves the file
pointer to the beginning of the file.
*/
#include <stdio.h>
int main(void)
{
FILE *stream;
int result;
if (stream = fopen("myfile.dat", "r"))
{ /* successful */
if (fseek(stream, 0L, SEEK_SET)); /* moves pointer to */
/* the beginning of the file */
{ /* if not equal to 0
then error ... */
}
else {
/* fseek() successful */
}
}
Like this can one move the file pointer to the next line immediately after that line
BO_ 377 FC_DM_MISC: 8 FC
SG_ DATA3 m11 : 31|8#0+ (1,0) [0|0] "" DM
These are the two lines and I want to program in a way that when one identifies the number 377 the pointer should now go to the next line i.e., to the line SG_ DATA3 inspite of the white spaces after 8 FC. How can one do that using fseek in C?
Try this code . It may help you .Here the Each line of the Input file is converted to string ,since string manipulation is very simple comparing to complex fseek() function.This may not be perfect answer but this will be very simple solution.
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE *stream;
int result;
char tmp[100]; // assuming that max length of a line in myfile.dat is 100.
if (stream = fopen("myfile.dat", "r"))
{ /* successful */
fscanf(stream, "%100[^\n]", tmp); // assuming that max length of a line in myfile.dat is 100.
printf("%s", tmp);
if (strstr(tmp, "377"))
{ // check for 337
fscanf(stream, "%100[^\n]", tmp); // next line is in the string tmp .
// continue your program.
//printf("%s", tmp);
}
}
}
fseek is used for binary data, if you work on a text file you should use either fgets or getline(recommended to use getline).
There's an open discussion of "fgets() vs getline" and many say that "fgets is deprecated" is only a gcc propaganda in favor to their specific getline().
A possible flaw in fgets() is that it doesn't tell you anything if there are null bytes being read, something you can get away with getline().
But then again if you don't like gcc, or use something different, use fgets(). If you are stuck with gcc, then use getline().
Any idea why I get 0.000000 with this printf? I checked the file and it was created fine
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
double doub1;
FILE *p;
if((p=fopen("data.txt","wb+"))==NULL)
puts("no");
fprintf(p,"%lf#%lf\n%lf%s",3.9458,314.32133,32.3,"hello");
fscanf(p,"%lf",&doub1);
printf("%lf",doub1);
}
To write to a stream opened with + and read from the same stream you need to flush the output first:
fflush(p);
However this does not reposition the file position indicator. To read characters you already wrote, you need to seek back to them. There is not a separate file position indicator for reading and writing:
fseek(p, 0, SEEK_SET); // go to start of file
The fseek does an implicit flush so you don't need to do fflush if you are doing fseek.
Also, you should check the return value of fscanf before trying to print the output. If the scan failed then you are printing an uninitialized variable.
I wanted to write, read and print to and from the same file. But when the program executes, it can write but it can't read or print the data I have written. When I execute the program, it stops working after writing to the file. I have verified that the file (penny.txt) contains data after the write operation.
I don't know where this is going wrong - how can I read and print the data?
I'm quite new to this, so please take that in mind when answering.
#include<stdio.h>
int main()
{
char ch;
char penny[50],pen[50];
FILE *Object;
Object = fopen("Penny.txt","w+");
fgets(penny, sizeof penny, stdin);
fprintf(Object,penny);
fscanf(Object,"%s",pen);
printf("%s",pen);
return 0;
}
You're at the end of the file when you call fscanf(). Use fseek to return to the beginning:
/* this ignores a whole host of other issues */
fprintf(Object,penny);
/* optional: fflush(Object); */
/* after the call to fprintf you're at the end of the "stream" in this case,
* go back to the beginning:
*/
fseek(Object, 0, SEEK_SET);
/* now we have something to read! */
fscanf(Object,"%s",pen);
printf("%s\n",pen);
You did not notice this problem due to a complete lack of error checking. fopen, fprintf, and fscanf all have error conditions listed, and all use their return value to signal a problem. You ignore these return values at your own peril.
#include<stdio.h>
int main()
{
//char ch;//unused!
char penny[50],pen[50];
FILE *Object;
Object = fopen("Penny.txt","w+");
fgets(penny, sizeof penny, stdin);
fprintf(Object,"%s", penny);//it troubled indicator(%) is included
fflush(Object);//Buffer flush : So that there is no wrote
rewind(Object);//rewind the position of access to the file
fscanf(Object,"%s",pen);
printf("%s",pen);
return 0;
}
You need to Use fseek() to move back the file current position inside the file.
int fseek ( FILE * stream, long int offset, int origin );
Reposition stream position indicator
Sets the position indicator associated with the stream to a new position.
stream
Pointer to a FILE object that identifies the stream.
offset
Binary files: Number of bytes to offset from origin.
Text files: Either zero, or a value returned by ftell.
origin
Position used as reference for the offset. It is specified by one of the following constants defined in exclusively to be used as arguments for this function:
Constant Reference position
SEEK_SET Beginning of file
SEEK_CUR Current position of the file pointer
SEEK_END End of file
*
try this:
#include<stdio.h>
int main()
{
char ch;
char penny[50],pen[50];
FILE *Object;
Object = fopen("Penny.txt","w+");
fgets(penny, sizeof penny, stdin);
fprintf(Object,penny);//now the file is in EOF
fseek(Object,-1*(strlen(penny),SEEK_CUR);//<===move back |penny| in the file
/* optional or:fseek(Object,0,SEEK_SET);<===move to start of file */
fscanf(Object,"%s",pen);
printf("%s",pen);
return 0;
}
I am dealing with a code which reading data from a binary file. The code is given here. Would anyone please make clear to me the role of fseek and fread here.
fc = fopen(CLOUDS_FILE, "rb");
if (fc == NULL){ fputs("File open error.\n", stderr); exit(1); }
crs = aux[CLRS];
fpos = (int) (pixel[2]*crs*crs + pixel[1]*crs + pixel[0]);
flsz = sizeof(fd);
fseek(fc, fpos*flsz, 0);
rd = fread((void *) &fd, flsz, 1, fc);
if (rd != 1){ fputs("Read error.\n", stderr); exit(1); }
fclose(fc);
fseek() changes the file offset. fread() reads data starting from the current offset, incrementing the offset by the number of elements read.
(Or is the question something else entirely? I mean, the above is something one can trivially figure by reading the manpages)
The binary file reading is done with an internal 'pointer', just like text editors have a cursor position when editing something. When opening the file in reading mode (using fopen) the pointer will be at the beginning of the file. Read operations (like fread, which will read a specified number of bytes from the stream) start reading at the pointer position and usually advance the pointer when they're done. If it is only necessary to read a specific part of the file, it is possible to manually set the pointer to a certain (relative or absolute) position, this is what fseek is used for.
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
The fseek() function sets the file position indicator for the stream
pointed to by stream. The new position, measured in bytes, is obtained
by adding offset bytes to the position specified by whence. If whence
is set to SEEK_SET, SEEK_CUR, or SEEK_END, the offset is relative to
the start of the file, the current position indicator, or end-of-file,
respectively.
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
The function fread() reads nmemb elements of data, each size bytes
long, from the stream pointed to by stream, storing them at the loca‐
tion given by ptr.
Sure, fseek is forwarding the "read from" index in the file to a calculated offset in CLOUDS_FILE, while fread is reading one object of size sizeof(fd) (whatever fd is, as that's not in your pasted code) into fd.
When I am using fgetpos(fp,&pos), the call is setting pos to a negative value where pos is of type fpos_t. Can some one explain why this is happening?
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
#define MAX_TAG_LEN 50
char filename[1000] = "d:\\ire\\a.xml";
//extract each tag from the xml file
int getTag(char * tag, FILE *fp)
{
//skip until a beginning of a next
while(!feof(fp))
if((char)fgetc(fp) == '<')break;
if(!feof(fp)){
char temp[MAX_TAG_LEN]={0};
char *ptr;
int len;
fpos_t b;
fgetpos(fp,&b); // here the b is containing -ve values.....???
fread(temp,sizeof(char),MAX_TAG_LEN - 1,fp);
temp[MAX_TAG_LEN-1] = 0;
ptr = strchr(temp,'>'); //search of ending tag bracket
len = ptr - temp + 1;
sprintf(tag,"<%.*s",len,temp); //copy the tag
printf("%s",tag); //print the tag
b += len; //reset the position of file pointer to just after the tag character.
fsetpos(fp,&b);
return TRUE;
}
else{
return FALSE;
}
}
int main()
{
int ch;
char tag[100]={0};
FILE *fp = fopen(filename,"r");
while(getTag(tag,fp)){
}
fclose(fp);
return 0;
}
where a.xml is a very basic xml file
<file>
<page>
<title>AccessibleComputing</title>
<id>10</id>
<redirect />
<revision>
<id>133452289</id>
<timestamp>2007-05-25T17:12:12Z</timestamp>
<contributor>
<username>Gurch</username>
<id>241822</id>
</contributor>
<minor />
<comment>Revert edit(s) by [[Special:Contributions/Ngaiklin|Ngaiklin]] to last version by [[Special:Contributions/Rory096|Rory096]]</comment>
<text xml:space="preserve">#REDIRECT [[Computer accessibility]] {{R from CamelCase}}</text>
</revision>
</page>
</file>
The code is working for some xml files but for the above xml file it is stoping after printing the first tag.
According to the cplusplus.com description of fpos_t:
fpos_t objects are usually created by a call to fgetpos, which returns a reference to an object of this type. The content of a fpos_t is not meant to be read directly, but only to use its reference as an argument in a call to fsetpos.
I think that means that in theory the value of an fpos_t could be arbitrarily positive or negative, so long as the implementation treats it correctly. For example, fpos_t could be some offset from the end of the file rather than the beginning, in which case negative values make sense. It also could be some weird bit-packed representation that would use each bit, including the sign bit, to encode some other information about the file position.
Finally I found the error....
msdn says
You can use fseek to reposition the
pointer anywhere in a file. The
pointer can also be positioned beyond
the end of the file. fseek clears the
end-of-file indicator and negates the
effect of any prior ungetc calls
against stream.
When a file is opened for appending
data, the current file position is
determined by the last I/O operation,
not by where the next write would
occur. If no I/O operation has yet
occurred on a file opened for
appending, the file position is the
start of the file.
For streams opened in text mode, fseek has limited use, because
carriage return–linefeed translations
can cause fseek to produce unexpected
results. The only fseek operations
guaranteed to work on streams opened
in text mode are:
Seeking with an offset of 0 relative
to any of the origin values. Seeking
from the beginning of the file with an
offset value returned from a call to
ftell.
once fopen call is modified from "r" to "rb" it worked fine....
thanks