Foros del Web » Programación para mayores de 30 ;) » C/C++ »

[SOLUCIONADO] Ficheros binarios

Estas en el tema de Ficheros binarios en el foro de C/C++ en Foros del Web. Hola a todos, Necesito ayuda con un problemita y es que estoy empezando con la lectura y escritura de ficheros binarios en C++. Teniendo un ...
  #1 (permalink)  
Antiguo 31/05/2013, 04:56
 
Fecha de Ingreso: mayo-2013
Ubicación: Granada
Mensajes: 8
Antigüedad: 11 años
Puntos: 0
Ficheros binarios

Hola a todos,

Necesito ayuda con un problemita y es que estoy empezando con la lectura y escritura de ficheros binarios en C++.

Teniendo un archivo de texto con un número indeterminado de enteros separados cada uno por espacios, tabuladores o saltos de línea quiero leerlos y escribirlos en un fichero binario. He creado un programa para leer y escribir de uno en uno pero ahora me piden escribir en el fichero de salida en bloques de 512 bytes. Para ello utilizo un buffer con un tamaño de 512 usando la funcion write() para leer y la funcion read() para escribir pero el fichero de salida no está en formato binario.

Gracias de antemano. Un saludo.
  #2 (permalink)  
Antiguo 31/05/2013, 05:09
 
Fecha de Ingreso: mayo-2013
Ubicación: Granada
Mensajes: 8
Antigüedad: 11 años
Puntos: 0
Respuesta: Ficheros binarios

Código C++:
Ver original
  1. #include <iostream>
  2. #include <fstream>
  3. #include <stdlib.h>
  4.  
  5. using namespace std;
  6.  
  7.  
  8. int main (int argc, char **argv)
  9. {
  10.     const int TAM_BUFFER = 512;
  11.     char buffer [TAM_BUFFER];  
  12.  
  13.    
  14.     ifstream fi;
  15.     ofstream fo;
  16.  
  17.    
  18.     if (argc != 2) {
  19.         cerr << "Error: Numero de argumentos incorrecto\n";
  20.         cerr << "Formato: " << argv[0]<< " <fich_in> <fich_out>\n";
  21.         exit (1);
  22.     }
  23.    
  24.     fi.open (argv[1]);
  25.    
  26.     if (!fi) {
  27.         cerr << "Error: no pudo abrirse " << argv[1] << endl;
  28.         exit (2);
  29.     }
  30.    
  31.     fo.open(argv[2], ios::binary);
  32.    
  33.     if (fo.fail())
  34.     {
  35.         cerr << "Error: No pudo crearse " << argv[2] << endl;
  36.         exit (2);
  37.     }
  38.  
  39.    
  40.     while (fi.read(reinterpret_cast<char*>(buffer), TAM_BUFFER))
  41.         fo.write(buffer, TAM_BUFFER);
  42.  
  43.     fo.write(buffer, fi.gcount());
  44.  
  45.    
  46.     fi.close ();
  47.     fo.close ();
  48.  
  49.     return (0);
  50. }
  #3 (permalink)  
Antiguo 01/06/2013, 08:08
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Ficheros binarios

"...me piden escribir en el fichero de salida en bloques de 512 bytes..."

Esto puede tener varias interpretaciones: bloques de texto char[512] o bloques de enteros int[128].

El archivo original tiene caracteres numericos? Es decir un byte (p.ej.) con el caracter '2', o dos bytes con los caracteres '98', esto seria un archivo con caracteres numericos (estando separados por espacios, saltos de linea o lo que quiereas). El otro caso es que el archivo contenga enteros como tales, es decir 4 bytes para cada dato equivalente a numero entero.

Si estas en el primer caso puedes guardar un buffer de texto de 512, guardar el entero como lista de caracteres numericos dentro del buffer y escribir los 512 bytes de bufer en el archivo resultante aun cuando no todos los bytes del bufer esten usados por las lista de caracteres numricos; dicho de otra forma:

Código:
//lees '789'
buffer[0] = '7';
buffer[1] = '8';
buffer[2] = '9';
buffer[3] = 0;
...
buffer[511] = 0;

//escribes el buffer de 512
fo.write(buffer, 512);
Si estas en el segundo caso obviamente la lectura que estas usando fallará.

Saludos
vosk
  #4 (permalink)  
Antiguo 01/06/2013, 08:24
 
Fecha de Ingreso: mayo-2013
Ubicación: Granada
Mensajes: 8
Antigüedad: 11 años
Puntos: 0
Respuesta: Ficheros binarios

Más bien estoy en el segundo caso, el archivo original contiene enteros y debo tratarlos como un entero (4 bytes) supongo. El caso es que no sé como hacer la lectura de por ejemplo 128 enteros (para escribir en bloques de 512 bytes). Las funciones read y write leen cadenas de caracteres. ¿Cómo puedo hacerlo?

Muchas gracias vosk.
  #5 (permalink)  
Antiguo 01/06/2013, 09:38
 
Fecha de Ingreso: mayo-2013
Ubicación: Granada
Mensajes: 8
Antigüedad: 11 años
Puntos: 0
Respuesta: Ficheros binarios

Ya lo he solucionado.
Código C++:
Ver original
  1. #include <iostream>
  2. #include <fstream>
  3. #include <stdlib.h>
  4.  
  5. using namespace std;
  6.  
  7.  
  8. int main (int argc, char **argv)
  9. {
  10.     const int TAM_BUFFER = 128;
  11.     int buffer [TAM_BUFFER];  
  12.     int entero, cont=0;
  13.    
  14.    
  15.     ifstream fi;
  16.     ofstream fo;
  17.  
  18.    
  19.     if (argc != 3) {
  20.         cerr << "Error: Numero de argumentos incorrecto\n";
  21.         cerr << "Formato: " << argv[0]<< " <fich_in> <fich_out>\n";
  22.         exit (1);
  23.     }
  24.    
  25.     fi.open (argv[1]);
  26.    
  27.     if (!fi) {
  28.         cerr << "Error: no pudo abrirse " << argv[1] << endl;
  29.         exit (2);
  30.     }
  31.    
  32.     fo.open(argv[2], ofstream::binary);
  33.    
  34.     if (fo.fail())
  35.     {
  36.         cerr << "Error: No pudo crearse " << argv[2] << endl;
  37.         exit (2);
  38.     }
  39.  
  40.    
  41.     fi >> entero;
  42.    
  43.     while (!fi.eof())
  44.     {
  45.         if(cont==TAM_BUFFER){
  46.             for(int i=0; i<TAM_BUFFER; i++)
  47.                 fo.write ((const char *) (&buffer[i]), sizeof (int));
  48.         }
  49.         buffer[cont];
  50.         cont++;
  51.        
  52.         fi >> entero;
  53.        
  54.     }
  55.    
  56.     for(int i=0; i<cont; i++)
  57.         fo.write ((const char *) (&buffer[i]), sizeof (int));
  58.  
  59.    
  60.     fi.close ();
  61.     fo.close ();
  62.  
  63.     return (0);
  64. }

Gracias. Un saludo.
  #6 (permalink)  
Antiguo 01/06/2013, 10:24
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Ficheros binarios

Creo que deberias echarle otro vistazo a tu codigo: que tienes dentro de buffer? No hay nada porque no le has asignado nada ok? El codigo compila y la aplicacion funciona porque accedes a las posiciones existentes de buffer y envias al archivo punteros a esas posiciones: los punteros ocupan 4 bytes, igual que el tamaño de entero que le indicas:

Código:
fo.write (
        (const char *) (&buffer[i]),//puntero a caracter, 4 bytes
        sizeof (int)//tamaño de los tipos entero, 4 bytes
);
Si quieres guardar el entero cargado de 'fi' en 'fo' puedes enviar el puntero al entero como bufer de datos indicando el tamaño que debe escribir

Código:
fo.write ((const char *)&entero, sizeof (int));
Saludos
vosk
  #7 (permalink)  
Antiguo 01/06/2013, 10:33
 
Fecha de Ingreso: mayo-2013
Ubicación: Granada
Mensajes: 8
Antigüedad: 11 años
Puntos: 0
Respuesta: Ficheros binarios

Si, me he dado cuenta después al sacarlos por pantalla y es que me imprimía basura. Se me había olvidado asignarle a cada posición del buffer el entero.
Solución:
Código C++:
Ver original
  1. buffer[cont] = entero;
  #8 (permalink)  
Antiguo 01/06/2013, 10:46
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Ficheros binarios

Ok solucionas lo de los datos pero no has tenido en cuenta que sizeof(buffer[cont]) < sizeof(entero); dicho de otra forma: un char puede guardar entre enteros de valores -128 y 128 (0 incluido), un unsigned char puede guardar enteros de valores entre 0 y 255, pero un entero puede guardar enteros de valores entre -32767 y 32767 (INT_MAX). Dicho aun de otra forma, cuando hagas buffer[0] = 128 te quedará que buffer[0] tiene el valor -1, con lo cual la aplicacion aunque funciona no opera correctamente.

Saludos
vosk
  #9 (permalink)  
Antiguo 01/06/2013, 10:59
 
Fecha de Ingreso: mayo-2013
Ubicación: Granada
Mensajes: 8
Antigüedad: 11 años
Puntos: 0
Respuesta: Ficheros binarios

Cierto, perdón por el descuido. Inicializando el contador cuando se llega al límite debe solucionarse, no?

Es decir:
Código C++:
Ver original
  1. if(cont==TAM_BUFFER){
  2.        for(int i=0; i<TAM_BUFFER; i++)
  3.                 fo.write ((const char *) (&buffer[i]), sizeof (int));
  4.        cont = 0;
  5. }

Gracias.
  #10 (permalink)  
Antiguo 01/06/2013, 11:33
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Ficheros binarios

Uy perdona, no se porque estoy todo el rato pensando que aun tenias char buffer[] y por eso te comento lo de los tamaños, ha sido un error por mi parte. Eso me pasa por no terminmar de leer los posts :)

Saludos
vosk
  #11 (permalink)  
Antiguo 01/06/2013, 11:41
 
Fecha de Ingreso: agosto-2012
Mensajes: 601
Antigüedad: 11 años, 8 meses
Puntos: 83
Respuesta: Ficheros binarios

Por cierto, ya que tienes la lista no necesitas guardar el valor a 'entero' para luego asignarlo a la posicion de la lista:

Código:
cont = 0;
fi >> buffer[cont];
while (!fi.eof()) {
    if(++cont == TAM_BUFFER) {
            for(int i=0; i<TAM_BUFFER; i++) {
                fo.write ((const char *) (&buffer[i]), sizeof (int));
            }
            cont = 0;
        }

    fi >> buffer[cont];
    }
Saludos
vosk

Etiquetas: c++, ficheros
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 23:28.