9.f – 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 t_pers, y cada uno de los campos de la estructura estarán separados por el carácter «|». Se podría utilizar cualquier carácter, pero 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; }