Reputation: 1552
still really new to C but starting to get the hang of it....
My program is supposed to create/write a file and store information from an array of structures. That part is fine. What im having trouble with is reading from that file back into an empty array of structures....
here's my structs:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX 100
struct Video {
char name[1024]; //name
int ranking; // Number of viewer hits
char url[1024]; // YouTube URL
};
struct Video Collection[MAX];
here's my load method which reads from my file back into my array of structures:
void load()
{
FILE *fileName;
fileName = fopen("ranking.dbm", "rb");
if (fileName != NULL){
fread (Collection,1,1,fileName);
}
else {
printf("ERROR");
}
}
also here is my write method:
void save()
{
FILE * pFile;
pFile = fopen ( "Ranking.dbm" , "wb" );
fwrite (Collection, 1 , sizeof(Collection), pFile );
fclose (pFile);
}
however when i print out my array collection
after loading.... its empty... even though i can see my file in the project folder and open it and verify that the data is in there....
am i correct in thinking that i dont need a buffer since i don't need to do any processing on it before using it?
also since i've already statically allocated space for memory.... am i correct in thinking that i can just read directly into the array?
here is my print code:
void printall()
{
int i;
printf("\nCollections: \n");
for(i = 0; i < tail; i++)
{
printf("\nVideo Name: %s", Collection[i].name);
printf("\nRanking (Hits): %d", Collection[i].ranking);
printf("\nURL: %s", Collection[i].url);
printf("\n");
}
}
Upvotes: 1
Views: 17199
Reputation: 49493
I'm seeing a few issues here.. first how you read the file:
fread (Collection,1,1,fileName);
This will read into collection 1 byte from fileName
into Collection
You should check the return status of fread()
, when it's successful it tells you the total number of bytes to be read. (parameter 2 * parameter 3, or 1*1 in your case).
When I modify your read code like this:
fread(Collection, sizeof(struct Video), 1, fileName);
It does successfully read from the file... however you have a different problem now. Let's say your file contained this:
something 5 http://something.com
nothing 3 http://nothing.com
So (I think) that's the format for your file, a name (ASCII), a ranking (int), and URL (ASCII). Now let's say your main()
function looked like this:
int main ()
{
load();
printall();
return 0;
}
What you'd get back on stdout
would be something like:
Collections:
Video Name: something 6 http://something.com
nothing 3 http://nothing.com
Ranking (Hits): 0
URL:
The reason is because you declared your array with static (and very large) elements. The fread()
will try to read in the sizeof(struct Video)
which is 1024+4+1024 bytes, so unless every one of your lines is the exact size (1024 chars for name and url) then you're going to get what looks like messed up or empty data.
I would suggest reading until you hit a space instead and storing each value in the correct element instead of trying to read out the full file into an array.
EDIT:
If you want to populate your array like:
fread(myarray, sizeofstruct, numberofstructs, file);
You have to guarantee the data length. In your example you'd have to say "name is however many characters, + blank spaces = 1024" and same for URL. That seems to be a horrible space waster. The better bet is to populate your array one element at a time:
for(0 to last_element){
set myarray.name = data until first space
set myarray.ranking = (int)data until second space
set myarray.url = data until newline
}
You can use fscanf()
to read until a whitespace.
Frankly if you're going to populate one element at a time I'd just use character pointers for name and url and dynamically assign memory so you don't have huge wasted arrays.
Upvotes: 2
Reputation: 179717
fread
is in fact designed to read arrays of structures from a file, but you have to use it correctly.
fread
's four parameters are as follows:
void * ptr, size_t size, size_t count, FILE * stream
The first parameter is where to put the data (in your case, Collection
). The second parameter is the size of each array element: in your case, you want to put sizeof(struct Video)
. The third parameter is the number of elements you want to read, in your case, MAX
. The fourth parameter is the file to read from.
If you want to read into an array like struct Video Collection[MAX]
, you would then use fread(Collection, sizeof(struct Video), MAX, file)
. fread
will return the total number of elements read, which will be ≤ MAX
.
Upvotes: 4
Reputation: 22562
First I have to assume you meant struct Video Collection[MAX];
else your upper part is invalid C.
Second: you are reading 1 byte into Collection.
Try
fread(Collection, sizeof(struct Video), MAX, fileName);
This will read up to MAX
times chunks of sizeof(struct Video)
bytes into Collection.
Upvotes: 1