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;
}