Pasar de Txt a Bin y de Bin a Txt ( Long fija y Variable)
Ejemplo de escritura en un archivo de texto con campos de longitud variable
En el ejemplo que sigue se creará un archivo de texto y se grabará una serie de datos sobre éste. Los datos a grabar serán del tipo Empleado, y cada uno de los campos de la estructura estarán separados por el carácter «|». Se podría utilizar cualquier carácter, dependiendo el enunciado del ejercicio o del negocio, en nuestro caso utilizaremos «|» porque el negocio no hace uso de este carácter dentro de sus datos (imagine que uno de los campos de la estructura fuera el correo electrónico y se utilizara el caracter «@» para separar los campos, se estaría añadiendo un campo extra que no existe con el dominio de la cuenta de email). El origen de los datos a grabar será el archivo binario creado en el ejemplo de escritura de archivos binarios. Es decir, la función leerá cada registro del archivo binario y lo escribirá en el archivo de texto separando cada campo con el carácter «|».
Si se abre el archivo generado con un editor de texto se podrá observar las diferencias en las longitudes entre los campos de diferentes registros y el carácter de separación entre los campos del registro.
De Binario a Txt con Longitud Fija y Variable: Los nombres de los archivos van a ingresarse por argumentos en el main ( Empleados.dat Empleados.txt V). Donde el primer argumento va a ser el nombre del archivo binario, el segundo argumento es el nombre del archivo de texto y el tercer argumento es si de longitud fija o variable.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define ERROR_ARCH 0
#define ERROR_SINMEM 0
#define TODO_OK 1
#define TAM_LINEA 200
#define ERROR 0
typedef struct
{
int d;
int m;
int a;
} Fecha;
typedef struct
{
int dni;
char apyn[100];
char sexo;
Fecha fnac;
float sueldo;
} Empleado;
typedef void(*BinaTxt)(const void *, FILE *); // PUNTERO A FUNCION
int archBinaTxt ( const char * narchb, const char * narcht, size_t tamreg, BinaTxt binatxt)
{
FILE * archb = fopen (narchb, "rb");
if(!archb)
return ERROR_ARCH;
FILE * archt = fopen (narcht, "wt");
if(!archt)
{
fclose(archb);
return ERROR_ARCH;
}
void * reg = malloc (tamreg);
if(!reg)
return ERROR_SINMEM;
fread(reg,tamreg, 1, archb);
while(!feof(archb))
{
binatxt(reg,archt);
fread(reg,tamreg, 1, archb);
}
fclose(archb);
fclose(archt);
free(reg);
return TODO_OK;
}
void empBinaTxtV(const void * reg, FILE * archt)
{
Empleado * emp = (Empleado *)reg;
fprintf(archt,"%d|%s|%c|%d/%d/%d|%.2f\n", emp->dni, emp->apyn, emp->sexo, emp->fnac.d, emp->fnac.m, emp->fnac.a, emp->sueldo);
}
void empBinaTxtF(const void * reg, FILE * archt)
{
Empleado * emp = (Empleado *)reg;
fprintf(archt,"%-8d%-20s%c%02d/%02d/%04d%8.2f\n", emp->dni, emp->apyn, emp->sexo, emp->fnac.d, emp->fnac.m, emp->fnac.a, emp->sueldo);
}
void generarEmpleados(char* ruta)
{
FILE * arch = fopen(ruta, "wb");
Empleado emp[5]=
{
{62312444, "Matias", 'M',{10,10,1987}, 100.0},
{22312444, "Carlos", 'M',{17,1,2003}, 200.0},
{32312444, "Juan", 'M',{21,10,1989}, 300.0},
{42312444, "Carla", 'F',{30,12,2015}, 400.0},
{22312444, "Mayra", 'F',{4,6,2000}, 500.0}
};
fwrite(emp, sizeof(Empleado),5,arch); // ya es un puntero por eso va sin & y mando la cantidad de registros que voy a guardar
fclose(arch);
}
int main (int argc, char* argv[])
{
generarEmpleados(argv[1]);
archBinaTxt(argv[1],argv[2],sizeof(Empleado),argv[3][0]=='V'?empBinaTxtV:empBinaTxtF);
return 1;
}
Pasar de Texto a Binario
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#define ERROR_ARCH 0
#define ERROR_SINMEM 0
#define TODO_OK 1
#define TAM_LINEA 200
#define ERROR 0
typedef struct
{
int d;
int m;
int a;
} Fecha;
typedef struct
{
int dni;
char apyn[100];
char sexo;
Fecha fnac;
float sueldo;
} Empleado;
typedef int (*TxtaBin)(char*,void *, bool*);
int archTxtaBin(const char* narcht, const char* narchb, size_t tamreg, TxtaBin txtabin)
{
FILE * archt = fopen(narcht, "rt");
if(!archt)
return ERROR_ARCH;
FILE * archb = fopen(narchb,"wb");
if(!archb)
{
fclose(archt);
return ERROR_ARCH;
}
bool errorFatal = false;
int ret;
char linea[TAM_LINEA];
fgets(linea,TAM_LINEA,archt);
void * reg = malloc (tamreg);
if(!reg)
return ERROR_SINMEM;
while(!feof(archt) && ! errorFatal)
{
ret = txtabin(linea, reg, &errorFatal);
if( ret == TODO_OK)
{
fwrite(reg,tamreg,1,archb);
}
if(!errorFatal)
fgets(linea,TAM_LINEA,archt);
}
fclose(archb);
fclose(archt);
return errorFatal?ERROR:TODO_OK;
}
int empTxtaBinV(char * linea, void * reg, bool * errorFatal)
{
Empleado * emp = (void*)reg;
char *act = strchr(linea,'\n');
if(!act)
{
*errorFatal = true;
return ERROR;
}
*act = '\0';
act = strrchr(linea,'|');
sscanf(act+1,"%f", &emp->sueldo);
*act = '\0';
act = strrchr(linea,'|');
sscanf(act+1,"%d/%d/%d",&emp->fnac.d,&emp->fnac.m,&emp->fnac.a);
*act = '\0';
act = strrchr(linea,'|');
emp->sexo=*(act+1);
*act = '\0';
act = strrchr(linea,'|');
strncpy(emp->apyn,act+1,100); // no pone el \0
emp->apyn[100]='\0';
*act = '\0';
sscanf(linea,"%d",&emp->dni);
return TODO_OK;
}
int empTxtBinF(char * linea, void * reg, bool * errorFatal)
{
Empleado * emp = (Empleado*)reg;
char* act = strchr(linea,'\n');
if(!act)
{
*errorFatal=true;
return ERROR;
}
*act = '\0';
act -= 10;
sscanf(act,"%f", &emp->sueldo);
*act = '\0';
act -= 8;
sscanf(act,"%2d/%2d/%4d", &emp->fnac.d,&emp->fnac.m,&emp->fnac.a);
*act = '\0';
act--;
emp->sexo = *act;
*act ='\0';
act-=20;
strncpy(emp->apyn,act,20);
emp->apyn[20]='\0';
*act = '\0';
sscanf(linea,"%d",&emp->dni);
return TODO_OK;
}
int main (int argc, char* argv[])
{
int ret =archTxtaBin(argv[1],argv[2],sizeof(Empleado),argv[3][0]=='V'?empTxtaBinV:empTxtBinF);
FILE *pbin;
Empleado emp;
pbin = fopen(argv[2],"rb");
if(!pbin)
{
printf("Error de lectura de archivo\n");
return ERROR;
}
printf("**********\nARCHIVO BINARIO\n**********\n\nDNI-NOMBRE-SEXO-FECHNAC-SUELDO\n");
while(fread(&emp,sizeof(Empleado),1,pbin))
printf("%-8d%-20s%c%02d/%02d/%04d%8.2f\n",emp.dni,emp.apyn,emp.sexo,emp.fnac.d,emp.fnac.m,emp.fnac.a,emp.sueldo);
fclose(pbin);
return ret;
}