Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Read Flat File Into Structure

Status
Not open for further replies.

jtrapat1

Programmer
Jan 14, 2001
137
US
I'm trying to load a flat fixed length file into a structure and I'm getting some garbage in the data fields.
Right now, I'm just trying to print to the screen the data that is in the file.
Eventually, I wanted to then connect to a database and run queries so that I could loop thru and load this data from the file into the appropriate table.

Can you look thru and see what I'm doing wrong.

Thanks in Advance
John

Here's my file definition and my main():
--------------------------------------------
struct record {
char bnumber[ 20 ];
char last_act_date[ 16 ];
char last_act_user[ 12 ];
char school_yr[ 4 ];
char work_level[ 1 ];
char agency[ 5 ];
char program[ 3 ];
char bill [1];
char fund_type[ 3 ];
char fund[ 3 ];
char account[ 2 ];
char fed_yr[ 4 ];
char object[ 1 ];
char sub_object[ 1 ];
char stat_sub_obj[ 3 ];
char priority[ 1 ];
char status[ 1 ];
char neg_code[ 3 ];
char transaction[ 5 ];
char req_type[ 1 ];
char rec_amt[ 20 ];
char cash_impact[ 20 ];
char desc[ 80 ];
char approp_rec_num[ 20 ];
char cat[ 2 ];
char order[ 4 ];
char type[ 1 ];
char workforce[ 12 ];
};

int main()
{
FILE *source;
int n_bytes = 0;
struct record cuts;
source = fopen("CUTS_2002.TXT","r");

if(!source)
{
printf("no data file found\n");
exit(0);
8 }

while (0 != (n_bytes = fread(&cuts, 1, sizeof(struct record), source)) )
{
printf("Bytes Read: %d\n", n_bytes);

printf("%s %s %s %s %s\n",
cuts.bnumber,
cuts.agency,
cuts.program,
cuts.bill,
cuts.fund);

fread(&cuts, 1, sizeof(struct record), source);
}
fclose(source);
 
You can do a fread only if the data is writteen using fwrite. If it is a text file then the data is most probably written using fprintf or manually in which case each member of the structure might have been written individually.
A sizeof a structure is not always the sum of the sizes of all its members. To align its boundaries to an even address it can add some extra bytes to it.

Also if the file you are trying to read was written on a different OS its alignment might differ from the OS where you are trying to read it. This could explain your junk.

Also you are reading twice once in the while condition and once at the end of it. Keep it only once.

Try fscanf instead of fread.
 
Does your data file contain record delimiters (like CR LF)?
Is your data file opened for binary read ?
/JOlesen
 
Thanks for the responses.
Here's one record in my data file:
------------
269483 2002051421565046KENNEDY 219108732GEN00100 6C000 DWAMTC A-25000000 -15000000 Cut the Executive's Empire Opportunity Fund Local Assistance appropriation 268655 EC 0
----------------------------
I counted 250 characters including a blank space at the end of each record.
My file doesn't have any crlf characters.
It matches up with my definition except for the null terminator.
Should I add this into the end of my file layout?
Also, I didn't open my file for binary read since it's all character data?
I'll try this and see if it makes a difference.

Thanks Again.
John
 
Suggestions :

1) If every record is followed by a binary zero, I would include this in the structure - and after each record read verify that it actually is zero.

2) The individual members being filled by the fread doesn't receive a binary zero to terminate the strings ?
If so, printf("%s %s .... will look like garbage ... Is that the garbage you mention ?
You could solve this by including a maxlength in the printf statement : printf("%.xs %.ys %.zs", ... where x y and z are the max length of the strings (struct members).
/JOlesen
 
Hi,
I see some imprecisions in posts.

A) If you :

while( fread(&cuts, 1, sizeof(struct record), source)) )
{
printf("Bytes Read: %d\n", n_bytes);
...
...
fread(&cuts, 1, sizeof(struct record), source);
}

You make 2 read each loop, you read all records, but print and test EOF only on an half of them. It is sufficent:

while( fread(&cuts, 1, sizeof(struct record), source)) )
{
printf( cuts.xxx ) ;
...
...
}

B1) fread can read all: binary,text,float:anything. You can:
fread( &myvar, 1, 4, source )
and myvar can be a long or char[4] ;

B2) bytes Alignment:
Its true: if you want, compiler can bound binary value
(data on which make aritmetic opertations) at mutliples
of its word lenght. In this case struct size may be not
the sum of single item:

struct x
{
long i ;
char c;
long j ;
}

If you "explicitely" use some flag in your compiler,
the size of struct may be 12 instead 9.
In jpatrat1' struct, there are only chars.

C) If you are really sure that file is done by records
each of 250 chars with blank and without crlf, the
way of while( fread() ) is right.
(It is almost strange, but if you are sure, OK .
If record has CRLF and data are text, you can loop
a fgets, put data in a buffer, them memcpy the useful
part, in yout struct)

D) The null or 0 or '\0' or how you want call it.
The problem is not the record terminator: we have other
way to detect record end: size, crlf, ecc.
The problem is for each field:

{
char bnumber[ 20 ];
char last_act_date[ 16 ];
...
}

On file, and in struct, after bnumber, there is last_act_date : there is not place for a '\0' ;
Is better maintain the struct so, and manage print
or copy of single item, in a nostandard C string way:

#define PRINT(x,y) printf( "%*.*s%c", sizeof(x), sizeof(x), x, y )

and in program use

PRINT( cuts.bnumber, ' ' ) ; // or '-', '^'
PRINT( cuts.xxxxxxx, ' ' ) ;
.......
PRINT( cuts.xxxxxxx, '\n' ) ;

-------

A similar op can be done to copy strings

#define STRCPY(x,y) memcpy(x,y,sizeof(x)) // or (y) depends




bye

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top