I'm having a problem.
I'm trying to create a file and then reading it again, saving the values in a new structure. But when I try to print the values I just get garbaje after 7 values.
What am I doing wrong?
Or maybe there is a fwrite limit
#include<stdio.h>
#include<stdlib.h>
struct estructura_salida
{
int num_art;
int exist;
};
int main (void)
{
fflush(stdin);
int i,j;
long reg;
struct estructura_salida listado[100];
struct estructura_salida ventas[100];
struct estructura_salida listadol[100];
struct estructura_salida ventasl[100];
for(i=0;i<100;i++)
{
listado[i].num_art = i+1;
listado[i].exist = i+20;
ventas[i].num_art = i+1;
ventas[i].exist = i+10;
}
printf("\ncargados\n");
for(i=0;i<100;i++)
{
printf("\n%i\t%i\t%i",listado[i].num_art,listado[i].exist,ventas[i].exist);
}
FILE *fp1;
FILE *fp2;
fp1 = fopen("C://stock.dbf","wt");
fp2 = fopen("C://ventas.dbf","wt");
fwrite(listado,sizeof(struct estructura_salida),200,fp1);
fwrite(ventas,sizeof(struct estructura_salida),200,fp2);
fclose(fp1);
fclose(fp2);
printf("\nleyendo el archivo");
fp1 = fopen("C://stock.dbf","rt");
fp2 = fopen("C://ventas.dbf","rt");
while(!feof(fp1))
{
fread(listadol,sizeof(listadol),1,fp1);
}
while(!feof(fp2))
{
fread(ventasl,sizeof(ventasl),1,fp2);
}
fclose(fp1);
fclose(fp2);
printf("\narchivo leido\n");
for(i=0;i<100;i++)
{
printf("\n%i\t%i\t%i",listadol[i].num_art,listadol[i].exist,ventasl[i].exist);
}
return 0;
}
this is how the console looks, I just get garbaje. console
Thank you!!
I believe you are almost certainly working on a Windows system because you used "wt"
in the fopen()
mode. The t
is not recognized by the C standard or most Unix systems. And also because you used fflush(stdin)
which is essentially meaningless on non-Windows systems but is defined to do a more or less useful task on Windows systems.
Your primary problem is that you use "wt"
to open a text file for writing, but when you use fwrite()
, you are writing binary data to a text file. That means that entries containing 10 or 13 are likely to cause chaos.
Use "wb"
(and "rb"
when reading). This is supported by the C standard and indicates that you are doing binary I/O, not text I/O, and prevents the I/O system from wreaking havoc on your data.
You are also writing 200 records when you only have arrays containing 100 records (as pointed out by R Sahu in their answer) — this is not a recipe for happiness, either.
Your loops using while (!feof(fp1))
are wrong; using while (!feof(file))
is always wrong. You keep reading over the same elements — listadol[0]
and ventasl[0]
, because you simply pass the array name to fread()
. You could read all the records back in one fread()
operation per file, or you need to index the array correctly (passing &listadol[i]
for example).
Strictly, you should verify that the fopen()
calls (in particular) are successful. Arguably, you should do the same for the fread()
and fwrite()
calls. The ultra-fanatic would check the fclose()
calls. If the data file is crucial, you should do that, just in case there wasn't enough space on disk, or something else goes radically wrong.
Putting the changes together, and using NUM_ENTRIES
to identify the number of entries (and changing it from 100 to 10 for compactness of output), I get:
#include <stdio.h>
#include <stdlib.h>
struct estructura_salida
{
int num_art;
int exist;
};
enum { NUM_ENTRIES = 10 };
int main(void)
{
struct estructura_salida listado[NUM_ENTRIES];
struct estructura_salida ventas[NUM_ENTRIES];
struct estructura_salida listadol[NUM_ENTRIES];
struct estructura_salida ventasl[NUM_ENTRIES];
for (int i = 0; i < NUM_ENTRIES; i++)
{
listado[i].num_art = i + 1;
listado[i].exist = i + 20;
ventas[i].num_art = i + 1;
ventas[i].exist = i + 10;
}
printf("\ncargados\n");
for (int i = 0; i < NUM_ENTRIES; i++)
{
printf("%i\t%i\t%i\n", listado[i].num_art, listado[i].exist, ventas[i].exist);
}
const char name1[] = "stock.dbf";
const char name2[] = "ventas.dbf";
FILE *fp1 = fopen(name1, "wb");
FILE *fp2 = fopen(name2, "wb");
if (fp1 == NULL)
{
fprintf(stderr, "Failed to open file %s for reading\n", name1);
exit(EXIT_FAILURE);
}
if (fp2 == NULL)
{
fprintf(stderr, "Failed to open file %s for reading\n", name2);
exit(EXIT_FAILURE);
}
fwrite(listado, sizeof(struct estructura_salida), NUM_ENTRIES, fp1);
fwrite(ventas, sizeof(struct estructura_salida), NUM_ENTRIES, fp2);
fclose(fp1);
fclose(fp2);
printf("\nleyendo el archivo");
fp1 = fopen(name1, "rb");
fp2 = fopen(name2, "rb");
if (fp1 == NULL)
{
fprintf(stderr, "Failed to open file %s for reading\n", name1);
exit(EXIT_FAILURE);
}
if (fp2 == NULL)
{
fprintf(stderr, "Failed to open file %s for reading\n", name2);
exit(EXIT_FAILURE);
}
int n;
for (n = 0; fread(&listadol[n], sizeof(listadol[n]), 1, fp1) == 1; n++)
;
int m;
for (m = 0; fread(&ventasl[m], sizeof(ventasl[m]), 1, fp2) == 1; m++)
;
fclose(fp1);
fclose(fp2);
printf("\narchivo leido\n");
if (n != m)
{
fprintf(stderr, "Read different numbers of records (%d from %s, %d from %s)\n",
n, name1, m, name2);
exit(EXIT_FAILURE);
}
for (int i = 0; i < n; i++)
{
printf("%i\t%i\t%i\n", listadol[i].num_art, listadol[i].exist, ventasl[i].exist);
}
return 0;
}
It would be better to use a function to open the files which checks for failure and reports the error and exits — an exercise for the reader.
The output from that is:
cargados
1 20 10
2 21 11
3 22 12
4 23 13
5 24 14
6 25 15
7 26 16
8 27 17
9 28 18
10 29 19
leyendo el archivo
archivo leido
1 20 10
2 21 11
3 22 12
4 23 13
5 24 14
6 25 15
7 26 16
8 27 17
9 28 18
10 29 19
A hex dump program shows that the two data files contain what you'd expect:
stock.dbf:
0x0000: 01 00 00 00 14 00 00 00 02 00 00 00 15 00 00 00 ................
0x0010: 03 00 00 00 16 00 00 00 04 00 00 00 17 00 00 00 ................
0x0020: 05 00 00 00 18 00 00 00 06 00 00 00 19 00 00 00 ................
0x0030: 07 00 00 00 1A 00 00 00 08 00 00 00 1B 00 00 00 ................
0x0040: 09 00 00 00 1C 00 00 00 0A 00 00 00 1D 00 00 00 ................
0x0050:
ventas.dbf:
0x0000: 01 00 00 00 0A 00 00 00 02 00 00 00 0B 00 00 00 ................
0x0010: 03 00 00 00 0C 00 00 00 04 00 00 00 0D 00 00 00 ................
0x0020: 05 00 00 00 0E 00 00 00 06 00 00 00 0F 00 00 00 ................
0x0030: 07 00 00 00 10 00 00 00 08 00 00 00 11 00 00 00 ................
0x0040: 09 00 00 00 12 00 00 00 0A 00 00 00 13 00 00 00 ................
0x0050:
There aren't any printable characters except the odd CR or LF in that, so the information on the right isn't all that informative. (Tested on a Mac running macOS 10.13.6 High Sierra, using GCC 8.2.0.)