I have a problem in a C program of mine where after I use fread(), the file pointer goes to the end of the file sometimes.
I'll try to explain better - the code looks something like:
dummy = ftell(fp);
fread(&buf, sizeof(unsigned char), 8, fp);
dummy = ftell(fp);
where fp is a file pointer to an opened file (opened it with "w+", I'm using it as a binary file and I know i'm supposed to have a "b" in there too, but I heard its not really important to add it..),
dummy is just an unsigned long variable,
and buf is unsigned char[8]
now, when debugging, at the ftell before the fread, dummy is 262062
at the ftell after the fread, dummy is 262640
even though I only 'moved' 8 bytes..
does anyone have any idea what can be the cause of this..?
thanks for your help :)
If you don't use the b to open the file, ftell() doesn't return the truth, just a sort of "cookie" that's only useful to fseek(). There are a lot of different implementations out there; check the man page for your system to find out more.
Related
When I run my program and I choose to see the product list, it doesn't print anything. After some time, I find out that the value of fl_size is always 0. Why is this?
void view_prdct_code_list() {
FILE *stock = fopen("stock.dat","r+");
assert(stock);
int fl_size=ftell(stock);
int prd_size= sizeof(product);
int quantity= fl_size/prd_size;
printf("fl_size=%d",fl_size);
fseek(stock,0,SEEK_SET);
prdct cprd= (product *)malloc (sizeof(product)*quantity);
assert(cprd);
int i;
fread(cprd,prd_size,quantity,stock);
for (i=0;i<quantity;i++){
printf("PRODUCT CODE: %d\n",cprd->code);
}
free(cprd);
fclose(stock);
}
ftell does not return the total size of the file; it returns the current read or write position within the file. You call ftell immediately after opening the file, so that position is the very beginning of the file. You can either use fseek(stock, 0, SEEK_END) to seek to the end before calling ftell, or you can drop down a layer and use fstat(fileno(stock)) to retrieve the file size directly from the OS.
Further notes:
Neither of these options will work if you are reading from a pipe. (In general, you need to check for the success of every single one of your file access operations.)
fread is not guaranteed to read the entire file in one gulp even if you ask it to.
As 'alk' points out, ftell returns a long, not an int.
If long is only 32 bits, it is possible for a file to be so large that its size does not fit in a long. If your program needs to handle files that big, you need to #define _FILE_OFFSET_BITS 64 at the top of every .c file (before all the includes) and use fseeko and ftello. (Or whatever the Windows equivalent is.)
You should be opening this apparently-binary file with mode "r+b".
Binary files with no file header (and in particular with no magic number, of at least four bytes, at offset zero) are a Bad Thing.
Do not cast the return value of malloc. (It is necessary to do this in C++, but in C it is not only unnecessary, it can hide bugs.)
Check man page for ftell, for example this one: http://linux.die.net/man/3/ftell
Here is the relevant part: "The ftell() function obtains the current value of the file position indicator for the stream pointed to by stream."
When you open the file, cursor position will be at the start. So distance from start will be zero. Therefore ftell returns zero.
To find the size of file, see this link: How can I get a file's size in C?. Here's a snippet in short:
fseek(fp, 0L, SEEK_END);
sz = ftell(fp);
Make sure to call fseek(fp, 0L, SEEK_SET); after above.
Because ftell returns the size from the beginning to the current position of the file.
fseek(stock,0,SEEK_SET);
Means you set the position to the first bite of the file.
Also you gotta set fl_size=ftell(stock); after the fseek.
I try to read a file to which my FILE* fp points and I want to know where the end of the file is. Therefore I use fseek(); At the end of the file, I want to write data from my structure data.
void printData(FILE *fp)
{
struct data tmp;
fseek(fp,0,SEEK_END);
while(fread(&tmp,sizeof(struct data),1,fp) > 0)
{
puts("test2");
printf("Vorname: %s\n",tmp.vorname);
printf("Nachname: %s\n",tmp.name);
printf("Adresse: %s\n",tmp.adresse);
}
}
This is how my structure is defined:
struct data
{
char name[30];
char vorname[20];
char adresse[50];
};
My Problem is, that the while loop isn't executed even once. Do I forgot something?
fseek(fp,0,SEEK_END) positions the file pointer at the end of the file (starting point end of the file offset 0), when you then try to read from the file fread of course doesn't read anything.
instead open the file in append mode and fwrite the number of records, these will be appended to the file.
The third variable '1' in fread actually indicates number of items to be read and you are just reading one item. Refer fread document for this:
http://pubs.opengroup.org/onlinepubs/009696899/functions/fread.html
After seeking to the end-of-file you won't be able to read anything. If you just want to know the file size, you can mybe use fstat() instead, or you do the fseek() after reading what you wanted to read, thad depends on what you're trying to achieve.
fread() is used for reading contents from file not for writing.
Use fwrite() for writing contents to file.
Like:
fwrite(&tmp , 1 , sizeof(struct data) , fp );
Read more about:
fread() and fwrite()
You are seeking to the start of the file, since you're setting the offset to 0. That doesn't sound like what you want to be doing, but on the other hand seeking to the end and then trying to read would also fail. I'm confused. :/
Could it be that you meant fwrite(), rather than `fread()? Not likely since the rest of the code prints the results after the I/O, which is logical for reading but not for writing.
It would be helpful with more information, like your file is opened and what it does contain when you run the program.
I am looking for the faster way to completely change the content of a file. It will be clear after the example:
a.txt:
I am a very very long (maybe not too long) file. I am pretty sure I could be longer.
After running the program, and according to the user's input it should become for instance:
user input:
Hi!
Then I tried to use fwrite.
The problem is that the rest of the file were still there, so I've got something like:
a.txt:
Hi!m a very very long (maybe not too long) file. I am pretty sure I could be longer
After some researching this is what I've done:
FILE
*a;
char
buffer[500];
a = fopen("a.txt", "r");
fread(buffer, sizeof(char), 500, a);
printf("%s\n", buffer);
a = freopen("a.txt", "w", a);
scanf("%s", buffer);
// rewind(a);
// fwrite(buffer, sizeof(char), strlen(buffer), a);
fwrite(buffer, sizeof(char), 10, a);
fclose(a);
Although it works, I want to know if there's a better way to do it.
You can just use ftruncate() POSIX function after fwrite() to truncate the file.
The "w" flag should create a file, truncating any existing content if it exists. That's what you need.
I haven't used freopen() before but suspect that's related to the problem. I would try simply closing the input file with fclose(), and then open the file again using fopen()?
I don't know of a better way to do this using portable C.
There are a few minor problems with your implementation.
You don't check for any errors that might have occurred, which is important in the real world. Especially freopen might return NULL on error, and if you assign that to you're original pointer you lose the ability to fclose the file.
You should also remember that normal C strings end with a 0 byte, but fread reads raw bytes so you should reserve space for that zero byte and provide it. scanf will write the zero byte so you can use strlen to determine how many bytes to tell fwrite to write instead of hardcoding 10.
Finally scanf is easy for mocking stuff up, but the way you have it now if the user provides more than 499 bytes you'll have a buffer overflow which can lead to very bad things.
I am wondering if this is the best way to go about solving my problem.
I know the values for particular offsets of a binary file where the information I want is held...What I want to do is jump to the offsets and then read a certain amount of bytes, starting from that location.
After using google, I have come to the conclusion that my best bet is to use fseek() to move to the position of the offset, and then to use fread() to read an amount of bytes from that position.
Am I correct in thinking this? And if so, how is best to go about doing so? i.e. how to incorporate the two together.
If I am not correct, what would you suggest I do instead?
Many thanks in advance for your help.
Matt
Edit:
I followed a tutorial on fread() and adjusted it to the following:
`#include <stdio.h>
int main()
{
FILE *f;
char buffer[11];
if (f = fopen("comm_array2.img", "rt"))
{
fread(buffer, 1, 10, f);
buffer[10] = 0;
fclose(f);
printf("first 10 characters of the file:\n%s\n", buffer);
}
return 0;
}`
So I used the file 'comm_array2.img' and read the first 10 characters from the file.
But from what I understand of it, this goes from start-of-file, I want to go from some-place-in-file (offset)
Is this making more sense?
Edit Number 2:
It appears that I was being a bit dim, and all that is needed (it would seem from my attempt) is to put the fseek() before the fread() that I have in the code above, and it seeks to that location and then reads from there.
If you are using file streams instead of file descriptors, then you can write yourself a (simple) function analogous to the POSIX pread() system call.
You can easily emulate it using streams instead of file descriptors1. Perhaps you should write yourself a function such as this (which has a slightly different interface from the one I suggested in a comment):
size_t fpread(void *buffer, size_t size, size_t mitems, size_t offset, FILE *fp)
{
if (fseek(fp, offset, SEEK_SET) != 0)
return 0;
return fread(buffer, size, nitems, fp);
}
This is a reasonable compromise between the conventions of pread() and fread().
What would the syntax of the function call look like? For example, reading from the offset 732 and then again from offset 432 (both being from start of the file) and filestream called f.
Since you didn't say how many bytes to read, I'm going to assume 100 each time. I'm assuming that the target variables (buffers) are buffer1 and buffer2, and that they are both big enough.
if (fpread(buffer1, 100, 1, 732, f) != 1)
...error reading at offset 732...
if (fpread(buffer2, 100, 1, 432, f) != 1)
...error reading at offset 432...
The return count is the number of complete units of 100 bytes each; either 1 (got everything) or 0 (something went awry).
There are other ways of writing that code:
if (fpread(buffer1, sizeof(char), 100, 732, f) != 100)
...error reading at offset 732...
if (fpread(buffer2, sizeof(char), 100, 432, f) != 100)
...error reading at offset 432...
This reads 100 single bytes each time; the test ensures you got all 100 of them, as expected. If you capture the return value in this second example, you can know how much data you did get. It would be very surprising if the first read succeeded and the second failed; some other program (or thread) would have had to truncate the file between the two calls to fpread(), but funnier things have been known to happen.
1 The emulation won't be perfect; the pread() call provides guaranteed atomicity that the combination of fseek() and fread() will not provide. But that will seldom be a problem in practice, unless you have multiple processes or threads concurrently updating the file while you are trying to position and read from it.
It frequently depends on the distance between the parts you care about. If you're only skipping over/ignoring a few bytes between the parts you care about, it's often easier to just read that data and ignore what you read, rather than using fseek to skip past it. A typical way to do this is define a struct holding both the data you care about, and place-holders for the ones you don't care about, read in the struct, and then just use the parts you care about:
struct whatever {
long a;
long ignore;
short b;
} w;
fread(&w, 1, sizeof(w), some_file);
// use 'w.a' and 'w.b' here.
If there's any great distance between the parts you care about, though, chances are that your original idea of using fseek to get to the parts that matter will be simpler.
Your theory sounds correct. Open, seek, read, close.
Create a struct to for the data you want to read and pass a pointer to read() of struct's allocated memory. You'll likely need #pragma pack(1) or similar on the struct to prevent misalignment problems.
Say I have a file pointer like this:
file_ptr = fopen(“test.txt”, “r+”);
and I want to change each char's ASCII value as I move through the stream (I am doing this as a cipher, so if there is a better or more efficient way to do this, please let me know).
I am trying to use a while(!feof(file_ptr)) {} loop with fgetc() and fputc, but the file_ptr will be pointing to the next char, so i want to know if there is something i can do point it backwards one spot.
Essentially, I want to know the file stream equivalent for:
char* blah="blah blah";
char* index=blah;
index++;/*how to navigate a file stream in this way*/
Yes: you can use the fseek function:
fseek(file_ptr, -1L, SEEK_CUR); // move backwards one character
Furthermore, after your fputc and before your fgetc, you'll want to call fseek again:
fseek(file_ptr, 0L, SEEK_CUR); // don't move
just to notify the system that you're switching between reads and writes, so that it knows to properly flush all buffers and whatnot. (Otherwise you might not actually be where you think.)
By the way, for this to work properly, you'll want to open the file in binary mode rather than text mode:
file_ptr = fopen("test.txt", "rb+");
since otherwise the within-C definition of "character" might not exactly match the inside-the-file definition of "character" (especially when it comes to line endings), and fseek might put you in the middle of one of the latter.