When I first run I would add 3 records, which gives me a count of 3. Then I fwrite
the count into a bin file, and the records into a bin file, then I close the program.
When I reopen it and then I fread
in and it will give me my 3 records and a count of 3. But from there on, no matter if I back up or when I read in, it will give me the same count 3 and 3 records, though since the count isn't being updated either this may be why fread
is only reading in the first time records.
I am not sure why the counter isn't updating. Both fread
and fwrite
are returning = success so I am not sure what`s up.
void backUp(PAYROLL employee[], long int *pCounter)
{
FILE *counter;
errno_t result1 = fopen_s(&counter, "c:\\myFiles\\counter.bin", "a+b");
if (result1 == 0){
fwrite(pCounter, sizeof(long int), 1, counter);
fclose(counter);
}
else
printf("Back up of counter failed! error:%d",result1);
FILE *record;
errno_t result2 = fopen_s(&record, "c:\\myFiles\\record.bin", "a+b");
if (result2 == 0){
fwrite(employee, *pCounter *sizeof(PAYROLL), 1, record);
fclose(record);
}
else
printf("Back up of record failed! error:%d", result2);
}
void upload(PAYROLL employee[], long int *pCounter)
{
FILE *counter;
errno_t result1 = fopen_s(&counter, "c:\\myFiles\\counter.bin", "a+b");
if (result1 == 0){
result = fread(pCounter, sizeof(long int), 1, counter);
fclose(counter);
printf("Counter:%d", *pCounter);
}
else
printf("Upload up of counter failed!");
FILE *record;
errno_t result2 = fopen_s(&record, "c:\\myFiles\\record.bin", "r+b");
if (result2 == 0)
{
result2 = fread(employee, *pCounter *sizeof(PAYROLL), 1, record);
printf("Upload successful!\n");
fclose(record);
}
else
printf("Error opening file!");
}
Transferring the most salient comments into an answer.
How do you know that
fread
andfwrite
are returning "success" when you have not checked their return value?
Jude commented:
I look through the debugger and step in to the function, result is giving me their success return values (if that's how it works).
You still need that in the program. Without that sort of checking, your code will be blown over by a puff of wind.
Looks like everywhere you open in append mode "a+b" you should probably be using something else ("rb" in upload() and "wb" in backUp() possibly?)
Jude commented:
I don't understand, is there a specific function for error checking? As I had always thought that error checking was just looking at what goes in the value of result and then I can go check what the value means?
Look at the specification of fread()
and
fwrite()
. They return the number of records written or read, which may be less than the number requested. If you get a short write, then you have a problem — maybe out of disk space. If you get a short read, it may be that you requested 100 records but there were only 1 or 10 or 99 available to read (or there was an error). If you don't capture and check the return value, you've no idea what happened.
Jude commented:
I see they read and write 1, but it still stores the first 3 elements of my struct array. I assume it's one because it's only writing my array?
fread()
(and fwrite()
too) give you considerable flexibility because you can supply the size of an item and the number of items separately. You use:
result2 = fread(employee, *pCounter *sizeof(PAYROLL), 1, record);
This tells fread()
to read 1
item of size *pCounter * sizeof(PAYROLL)
. You will get a result of 1
(success) or 0
(failure). You could have specified:
result2 = fread(employee, sizeof(PAYROLL), *pCounter, record);
which would tell you how many records of size sizeof(PAYROLL)
were read, up to a maximum of the value in *pCounter
. You might get 0 or 1 or …
Here is some workable code that does more or less what's required. The main()
program demonstrates working with 1, 2 and 3 records (and the names are a few kings and queens of England, along with the year of their ascension to the throne as their employee ID number). I had to create a minimal payroll structure since the question didn't provide one.
#include <stdio.h>
#include <string.h>
#include <errno.h>
typedef struct PAYROLL
{
long emp_id;
char emp_name[32];
} PAYROLL;
static const char counter_bin[] = "counter.bin";
static const char records_bin[] = "records.bin";
static
void backUp(PAYROLL employee[], long int *pCounter)
{
FILE *counter = fopen(counter_bin, "wb");
if (counter != 0){
fwrite(pCounter, sizeof(long int), 1, counter);
fclose(counter);
}
else
fprintf(stderr, "Back up of counter failed! error: %d %s\n", errno, strerror(errno));
FILE *record = fopen(records_bin, "wb");
if (record != 0){
fwrite(employee, *pCounter *sizeof(PAYROLL), 1, record);
fclose(record);
}
else
fprintf(stderr, "Back up of records failed! error: %d %s\n", errno, strerror(errno));
}
static
void upload(PAYROLL employee[], long int *pCounter)
{
FILE *counter = fopen(counter_bin, "rb");
if (counter != 0){
size_t result = fread(pCounter, sizeof(long int), 1, counter);
fclose(counter);
if (result != 0)
printf("Counter: %ld\n", *pCounter);
else
fprintf(stderr, "Failed to read counter\n");
}
else
fprintf(stderr, "Upload up of counter failed!\n");
FILE *record = fopen(records_bin, "r+b");
if (record != 0)
{
size_t result2 = fread(employee, *pCounter * sizeof(PAYROLL), 1, record);
if (result2 == 1)
printf("Upload successful!\n");
else
fprintf(stderr, "Failed to read records!\n");
fclose(record);
}
else
fprintf(stderr, "Error opening file!");
}
int main(void)
{
PAYROLL emps[] =
{
{ 1066, "William the Conqueror" },
{ 1819, "Victoria" },
{ 1689, "William and Mary" },
};
for (int i = 1; i <= 3; i++)
{
long emp_count = i;
printf("Employee count = %ld\n", emp_count);
backUp(emps, &emp_count);
upload(emps, &emp_count);
for (int j = 0; j < emp_count; j++)
printf("%4ld: %s\n", emps[j].emp_id, emps[j].emp_name);
}
return 0;
}
Note that I've factored out the file names so that you only have to change a single line to change the files used. Sample output:
$ Employee count = 1
Counter: 1
Upload successful!
1066: William the Conqueror
Employee count = 2
Counter: 2
Upload successful!
1066: William the Conqueror
1819: Victoria
Employee count = 3
Counter: 3
Upload successful!
1066: William the Conqueror
1819: Victoria
1689: William and Mary
$ odx counter.bin
0x0000: 03 00 00 00 00 00 00 00 ........
0x0008:
$ odx records.bin
0x0000: 2A 04 00 00 00 00 00 00 57 69 6C 6C 69 61 6D 20 *.......William
0x0010: 74 68 65 20 43 6F 6E 71 75 65 72 6F 72 00 00 00 the Conqueror...
0x0020: 00 00 00 00 00 00 00 00 1B 07 00 00 00 00 00 00 ................
0x0030: 56 69 63 74 6F 72 69 61 00 00 00 00 00 00 00 00 Victoria........
0x0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x0050: 99 06 00 00 00 00 00 00 57 69 6C 6C 69 61 6D 20 ........William
0x0060: 61 6E 64 20 4D 61 72 79 00 00 00 00 00 00 00 00 and Mary........
0x0070: 00 00 00 00 00 00 00 00 ........
0x0078:
$
(odx
is just a hex dump program. Pick your own program that does an equivalent job — od -c
is a fallback, though I don't particularly like its formatting.)