Sie sind auf Seite 1von 19

Universidad Nacional Autnoma de Nicaragua Len

Departamento de Computacin

Ficheros
Curso: Programacin Estructurada

Elaboradopor:

Eduardo Santiago Molina Poveda, M.Sc.

Contenido
1.
2.

Introduccin ...................................................................................................................................... 1
Flujos (Streams) ................................................................................................................................ 1
2.1.
Flujos de texto........................................................................................................................... 1
2.2.
Flujos binarios........................................................................................................................... 1
3. Qu es un fichero?........................................................................................................................... 1
3.1.
Posicin del fichero................................................................................................................... 2
3.2.
Buffers....................................................................................................................................... 2
3.3.
Los flujos estndar .................................................................................................................... 3
4. Apertura y cierre de ficheros............................................................................................................. 4
4.1.
Abriendo un fichero .................................................................................................................. 4
4.2.
Modos de acceso ....................................................................................................................... 5
4.3.
Cerrando un fichero .................................................................................................................. 7
5. Escritura y lectura de ficheros........................................................................................................... 8
5.1.
Manejo de errores...................................................................................................................... 8
5.1.1
Flags de estado y valores de retorno ................................................................................. 8
5.1.2
La variable errno ............................................................................................................... 8
5.2.
E/S sin formato.......................................................................................................................... 9
5.2.1
Lectura de caracteres......................................................................................................... 9
5.2.2
Devolviendo al flujo un carcter ledo.............................................................................. 9
5.2.3
Escribiendo caracteres....................................................................................................... 9
5.2.4
Lectura de cadenas (strings)............................................................................................ 10
5.2.5
Escritura de cadenas (strings) ......................................................................................... 11
5.2.6
Lectura y escritura de bloque de datos............................................................................ 12
5.3.
Entrada y salida con formato .................................................................................................. 14
6. Acceso aleatorio a ficheros ............................................................................................................. 14
6.1.
Obteniendo la posicin actual del fichero............................................................................... 14
6.2.
Estableciendo la posicin del fichero...................................................................................... 15

1.

Introduccin

Muchos programas requieren escribir datos en un fichero o hacia otros dispositivos como
impresoras o la pantalla, de igual manera requieren ser capaces de leer datos desde un fichero o
desdedispositivoscomoelteclado.EllenguajeCproveeunconjuntodefuncionesparabrindarestas
funcionalidades.Estedocumentopresentaunaguadedicadaalmanejodeficherosendicholenguaje.

2.

Flujos(Streams)

Desde el punto de vista de un programa en C, todos los tipos de ficheros y dispositivos para
entradaysalida(E/S)sonrepresentadoscomoflujosdedatoslgicos,sinimportarsielprogramalee
oescribeuncarcterounbyteounalneadetextoounbloquededatosdeuntamaodado.Los
flujos en C pueden ser flujos de texto o flujos binarios. Abrir un fichero por medio de la funcin
fopen()creaunnuevoflujoqueexistehastaquesecierraconlafuncinfclose().Cdelegalagestin
deficherosalentornodeejecucin,esdecir,elsistemaoperativoenelcualelprogramaseejecuta.
Demaneraque,unflujoesuncanalpormediodelcuallosdatosfluyendesdeelentornodeejecucin
haciaelprogramaodesdeelprogramahaciaelentornodeejecucin.

2.1. Flujosdetexto
Unflujodetextotransportaloscaracteresdeuntextoqueestdivididoenlneas.Unalneaesuna
secuenciadecaracteresconelcarcternuevalnea(\n)comodelimitadordelamisma.Dichalneade
textotambinpuedeservaca,esdecir,slocontieneelcarcternuevalnea.

LarepresentacininternadetextoenunprogramaCnotieneencuentaelsistemaenelcualel
programaseejecuta.
2.2. Flujosbinarios
Unflujobinarioesunasecuenciadebytesquesontransmitidossinmodificacin,estoquieredecir
quelasfuncionesdeE/Snorealizanningntipodeinterpretacindeloscaracteresdecontrolcuando
setrabajaconflujosbinarios.Losdatosescritosaunficheroatravsdeunflujobinariopuedenser
ledos(posteriormente)sincambiosenelmismosistema.Aunque,enalgunossistemaspuedehaber
unbyteceroadicionalagregadoalfinaldelflujo.

Usualmentelosflujosbinariossonutilizadosparaescribirdatosenformatobinario,porejemplo,
registrodebasesdedatossinserconvertidosentextooarchivosdesonidoovdeo.Siunprograma
leeelcontenidodeunarchivodetextoatravsdeunflujobinario,eltextoaparecerenelprograma
deacuerdocomofuealmacenado.

3.

Quesunfichero?

Un fichero representa una secuencia de bytes. Se utiliza funcin fopen() para abrir un fichero
determinado, sta asocia el fichero con un flujo e inicializa un objeto de tipo FILE, el cual contiene
todalainformacinnecesariaparacontrolarelflujo.Dichainformacinincluyeunpunteroalbuffer
delectura/escriturausado;unindicadordeposicindelfichero,elcualespecificalaposicinalaque

seaccedeenelfichero;yflags(banderas)paraindicarcondicionesdeerrorofinaldelfichero(endof
file=EOF).

Las diferentes funciones empleadas para abrir ficheros: fopen(), freopen() y tmpfile(), retornan un
punteroaunobjetoFILEparaelflujoasociadoconelficheroqueestsiendoabierto.Unavezqueel
ficherohayasidoabierto,sepuedeninvocarfuncionesparatransferirdatosomanipularelflujo.Tales
funciones reciben entre sus argumentos un puntero a FILE, ste especifica el flujo sobre el cual se
realizalaoperacinimplementadaporlafuncin.

A diferencia de las funciones anteriormente mencionadas, existen en la biblioteca de E/S ciertas


funcionesqueoperansobreelsistemadearchivos,yrecibencomoparmetrosunnombredearchivo
ynounpunteroaFILE.Estasfuncionesnorequierenqueunarchivoseaabiertoprimero.Entreellas
seincluyen:

Lafuncinremove(),staseencargadeeliminarunfichero(oundirectoriovaco).Lasintaxis
delafuncines:intremove(constchar*ruta).Lafuncinrecibecomoargumentounacadena
queserefieroalnombredelficheroaeliminar.Sielficherotienemsdeunnombre(casode
UNIX/Linux),remove()sloeliminaelnombreespecificadocomoparmetro,noelficheroen
s. De manera que, los datos seguiran accesibles de otra manera, aunque no a travs del
nombredearchivoeliminado.Lafuncinretorna0situvoxito,encasocontrario1.
La funcin rename(), sta cambia el nombre de un fichero o directorio. La sintaxis de la
funcin es: int rename(const char *nombreActual, const char *nombreNuevo) . Los
argumentosquerecibelafuncinsoncadenasdecaracteres,elprimeroparmetroserefiere
elnombreactualdelficheroyelsegundoalnuevonombreaestablecer.Lafuncinretorna0
situvoxito,encasocontrario1.

3.1. Posicindelfichero
De forma anloga a los elementos de array de caracteres, cada carcter en un fichero tieneuna
posicindefinida.Elindicadordeposicindelficheroenelobjetoquerepresentealflujodeterminala
posicindelsiguientecarcteraserledooescrito.

Un fichero se puede abrir en diferentes modos: lectura, escritura o agregacin. Al abrir un fichero
(paralecturaoescritura),elindicadordeposicindeficheroseubicaaliniciodelfichero,demanera
queelprximocarcteraseraccedidotienelaposicin0.Siseabreenmodoagregacin,elindicador
de posicin se ubica al final del fichero. Por cada operacin de lectura o escritura el indicador de
posicin se incrementa segn el nmero de caracteres ledos o escritos en el fichero. Este tipo de
accesoseconocecomoaccesosecuencial.

3.2. Buffers
Altrabajarconficheros,noeseficienteleeroescribircaracteresunoporuno.Porloantesdicho,
unflujoempleaunespaciodealmacenamientotemporal(buffer)enelcualseguardanloscaracteres,
los cuales son transferidos en bloques (o conjunto de caracteres) desde y hacia el fichero. Sin
embargo,algunasvecesnosedeseaemplearbuffering(almacenamientotemporal),porejemploen

casos que se produzcan un error de ejecucin en el programa y se quieran salvar los datos
inmediatamenteenunfichero.

Losflujossonbuffereadosdetresformas:
Fullybuffered:Loscaracteresenelbuffersontransferidosslocuandoelbufferestlleno,es
decir,muchoscaracteressonguardadostemporalmenteyescritoscomounsolobloque.
Linebuffered:Loscaracteresenelbuffersontransferidosslocuandouncarcternuevalnea
(\n)esescritoenlocuandoelbufferestlleno.
Sinbuffer(Unbuffered):Loscaracteressontransferidostanprontocomoseaposible.

Tambinesposibleforzarlatransferenciadeloscaracterescontenidosenunbufferdesalidadeun
flujo asociado a un fichero invocando a la funcin fflush(). El buffer tambin es vaciado (flushed)
cuandosecierraunflujo.

Pordefectocuandoseabreunarchivopormediodelafuncinfopen(),elnuevoflujocreadoesfully
buffered. Despus de abrirlo y antes de realizar la primera operacin de entrada/salida en l, es
posiblecambiarelmododebufferinginvocandolafuncinsetbuf()osetvbuf().

Lassintaxisdelasfuncionesanterioresson:
void setbuf(FILE *restrict flujo, char *restrict buf);
void setvbuf(FILE *restrict flujo, char *restrict buf, int tipo, size_t tam);

Lafuncinsetbuf()recibedosparmetros;elprimero,unpunteroaFILEasociadoalflujoabierto;yel
segundo,unpunteroacharquerepresentealnuevobufferautilizarenlugardelactual.Sibufnoes
NULL es responsabilidad el programador liberar la memoria referenciada por buf antes de cerrar el
flujo.SibufesNULLseasignaunbufferautomticamente.

setvbuf, adems de los argumentos presentes en la funcin anterior, incluye un tercer y cuarto
argumento:tipoytam,respectivamente.Elargumentotipopuedeserunodelossiguientesvalores:
_ONBF
unbuffered
_IOLBF
line-buffered
_IOFBF
fully buffered

Elargumentotampuedetenerunvalorcero,encuyocasoseobtieneunbufferdetamaoptimo;o
unvalorcero,exceptoparalosarchivossinbuffer.

3.3. Losflujosestndar
ExistentresflujosdetextoestndardisponiblesparatodoprogramaC,loscualesnorequierenser
abiertosdeformaexplcita.Estosson:
Puntero a FILE

stdin
stdout
stderr

Nombre

Standard input (Entrada estndar)


Standard output (Salida estndar)
Standard error output (Salida de error estndar)

Tipo de buffer

Line-buffered
Line-buffered
Unbuffered
3

stdin est asociado con el teclado, stdout y stderr estn asociados con la pantalla. Estas
asociacionespuedensermodificadasporredireccin.Unaredireccinconsisteencambiarelusopor
defectodelflujoypuederealizarsepormediodelafuncinfreopen().

//Ejemplo: redireccion.c
//Este ejemplo redirecciona la salida estndar al fichero datos.txt
#include<stdio.h>
int main(){
FILE *pf = freopen("datos.txt", "a", stdout); //Redireccionar stdout al fichero
If(pf != NULL){
printf("Este texto se redirecciona al fichero."); //La salida se escribe en el fichero
fclose(stdout); //Cerramos el flujo
}
return 0;
}

4.

Aperturaycierredeficheros

Para leer un fichero, crear uno nuevo o modificar (escribir)el contenido de uno existente, antes
debeabrirseelfichero.Adems,enelmomentodeapertura,tambindebeespecificarseelmodode
accesoalfichero:lectura,escrituraoalgunadeestasdoscombinaciones.Finalmente,cuandoseha
terminadoderealizarlasoperacionesdeE/Senelfichero,debecerrarseparaliberarrecursos.

4.1. Abriendounfichero
La biblioteca estndar de C provee la funcin fopen() para abrir un fichero. Tambin provee la
funcinfreopen()ytmpfile()paracasosespeciales,queseexplicaranposteriormente.

Elprototipodelafuncinfopen()es:
FILE *fopen(const char *restrict nombreFichero, const char* restrict modo);

LafuncinabreelficheroespecificadoenelargumentonombreFichero,stepuedecontenerunaruta
absolutaorelativadearchivo.Elsegundoargumento,modo,esunacadena,yespecficalosmodosde
accesoalfichero.LafuncinretornaunpunteroaFILE,esdecir,asociaelficheroconunnuevoflujo.

La funcin freopen() redirecciona un flujo. Similarmente a la funcin fopen() abre un fichero en el


modo especificado, sin embargo, en lugar de crear un nuevo flujo, asocia el fichero con un flujo
existente,queesespecificadoeneltercerargumento.Elficheropreviamenteasociadoconelflujoes
cerrado.Elusocomnesredireccinlosflujosestndar.

FILE *freopen(const char* restrict nombreFichero, const char *modo, FILE *restrict flujo);

La funcin tmpfile() crea un fichero temporal diferente a todos los archivos existentes y abre el
ficheroenmodobinarioparalecturayescritura.Sielprogramaterminanormalmente,elficheroes
borradoautomticamente.

4.2. Modosdeacceso
El modo de acceso es un argumento en las funciones fopen() y freopen(), ste determina qu
operaciones de E/S permite el flujo creado. Dichos valores de cadena estn restringidos a: r para
lectura,wparaescritura,aparaaadidura;enelcasomssimpleelargumentomodoslocontendr
uno de los caracteres anteriores. Sin embargo, el argumento modo puede tambin contener uno o
ambosdelossiguientescaracteres:+yb(sinimportarelordenenqueaparezcan,esdecir,+besigual
atenerb+).

El signo ms (+) en el argumento modo indica que el flujo permitir las operaciones de lectura y
escritura.Perohabrquetenercuidadoconnoalternarinmediatamenteestasoperaciones,esdecir,
que despus de una operacin de escritura se deber realizar un fflush() al flujo o invocar una
funcindeposicionamiento(fseek(),fsetpos()orewind())antesderealizarunalectura.Y
despusderealizarunaoperacindelecturasedeberinvocarunafuncindeposicionamientoantes
derealizarunaoperacindelectura.

Elcarcterbenelargumentomodoindicaqueelarchivoserabiertoenmodobinario,esdecir,que
elnuevoflujoasociadoalficheroserunflujobinario.Sinoseespecificaelcarcterb,entoncesel
flujocreadoserunflujodetexto.

Sielargumentomodocomienzaconr,elficherodeberexistirenelsistemadearchivos,sinodarun
errorindicandoquenosepudoabrir.Sielargumentomodocomienzaconw,elficherosercreadoen
casodenoexistir;ysiexiste,elcontenidodelficherosereliminado,porquelafuncinfopen()trunca
elficheroalongitudceroenmodoescritura(w).

Si el argumento modo incluye el carcter a (para agregacin) hace que la funcin fopen() cree el
fichero si ste no existe, si existe lo abre sin eliminar el contenido previo del mismo y ubica el
indicador de posicionamiento del fichero al final de ste, es decir, que automticamente todas las
operacionesdeescrituraquesehagandespusdeabrirelficheroserealizarnalfinaldelmismo.

A continuacin unos ejemplos donde se puede observar cmo utilizar la funcin fopen() con sus
diferentesmodos:

//Ejemplo1.c: Uso de fopen() para abrir un fichero en modo lectura.


#include<stdio.h>
int main(){
FILE *pf = fopen(datos.txt, r);
//Abre el fichero datos.txt en modo lectura (solamente)
if(pf != NULL){
//Se pudo abrir el fichero?
fclose(pf);
//Apertura del fichero con xito, cerrar el fichero.
return 0;
//retornar 0.
}
else
//No se pudo abrir el fichero
return -1;
//retornar -1
}

//Ejemplo2.c: Uso de fopen() para abrir un fichero en modo escritura


#include<stdio.h>
int main(){
FILE *pf = fopen(datos2.txt, w); //Abre el fichero datos.txt en modo escritura.
//Si el fichero existe, elimina el contenido del mismo y
//trunca su longitud a cero. Si no existe, lo crea.
if(pf != NULL){
//Se pudo abrir o crear el fichero?
printf(Fichero abierto satisfactoriamente);
fclose(pf);
//Apertura o creacin del fichero con xito, cerrarlo.
return 0;
}
else{
//No se pudo abrir o crear el fichero, retornar -1.
return -1;
}
}
//Ejemplo3.c: Uso de fopen() para abrir un fichero para agregacin.
#include<stdio.h>
int main(){
FILE *pf = fopen(datos3.txt, a); //Abrir fichero datos.txt en modo agregacin.
//Si el fichero existe, no se pierde su contenido
//Si no existe, se crea.
if(pf != NULL){
//Se pudo abrir o crear el fichero?
printf(Fichero abierto satisfactoriamente);
fclose(pf);
//S, entonces cerrarlo.
return 0;
}
else{
//No se pudo abrir o crear fichero, retornar -1.
printf(No se pudo abrir o crear fichero);
return -1;
}
}
//Ejemplo4.c: Uso de fopen() para abrir un fichero en modo lectura y escritura
#include<stdio.h>
int main(){
FILE *pf = fopen(datos4.txt, rw);//Abrir fichero datos.txt en modo lectura y escritura
//Si archivo no existe, no lo crea.
if(pf != NULL){
//Se pudo abrir fichero?
printf(Fichero abierto satisfactoriamente);
fclose(pf);
//Cerrar fichero
return 0;
}
else{
printf(No se pudo abrir fichero);
return -1;
}
}

//Ejemplo5.c: Uso de fopen() para abrir fichero en modo lectura y escritura


#include<stdio.h>
int main(){
FILE *pf = fopen(datos5.txt, w+); //En esta ocasin si el fichero no existe, se crea.
//Despus de creado o si existe se permiten operaciones
//de lectura y escritura.
if(pf != NULL){
printf(Fichero abierto satisfactoriamente);
fclose(pf);
return 0;
}
else{
printf(No se pudo abrir o crear fichero);
return -1;
}
}
//Ejemplo6.c: Uso de fopen() utilizando el modo r+
int main(){
FILE *pf = fopen(datos6.txt, r+); //Abrir fichero, permitiendo operaciones de lectura y
//escritura. El archivo debe existir.
if(pf != NULL){
printf(Fichero abierto satisfactoriamente);
fclose(pf);
//Cerrar fichero
return 0;
}
else{
printf(No se pudo abrir fichero.);
return -1;
}
}

4.3. Cerrandounfichero
Enlaseccinanteriorseobservelusodelafuncinfclose()paracerrarunficheroabierto
previamente.Elprototipodeestafuncines:
int fclose(FILE *pf);

Lafuncinvacacualquiercontenidopendienteenelbufferhaciaelfichero,cierraelficheroyliberala
memoriausadaporelbufferdelflujodeE/S.Lafuncinretorna0sinohuboerroroEOFencasode
error.

Cuandounprogramaterminatodoslosficherosabiertossoncerradosdeformaautomtica.Perolo
idealescerrarcualquierficheroabiertodespusdeterminardeprocesarlooantesdefinalizarel
programa,yaqueunerrorquecauseunafinalizacinabruptadelprogramasecaeenelriesgode
perderdatosnoguardados.
7

5.

Escrituraylecturadeficheros

Enesteapartadosedescribeunconjuntodefuncionesparaobtenerdatosdeunficherooescribir
datosenl.

5.1. Manejodeerrores
LasfuncionesdeE/Spermitenusarunaseriedemecanismosparaindicaralinvocadorcundose
haproducidounerror;stosmecanismosincluyenvaloresderetorno,flagsdeerroroEOFsobreel
objetoFILEylavariableglobalerrno.Esimportanteconocerqumecanismoempleardeacuerdo
conunafuncindada.

5.1.1
Flagsdeestadoyvaloresderetorno
MuchasfuncionesdeE/Sindicanlaocurrenciadeunerrorpormediodesusvaloresderetorno.
Adems,tambinseestableceunflagsobreelobjetoFILEquecontrolaelflujoencasodeproducirse
algnerrordelecturaoescritura.Parasaberqueflagseactiv,seutilizalafuncinferror().Por
ejemplo:
fputc(*, pf);
//Escribir un carcter en el flujo asociado a pf
if(ferror(pf))
//Si ocurri un error, indicarlo con un mensaje.
printf(Error en la escritura);
Por otra parte, el conjunto de funciones de lectura de E/S establecen el flag de EOF (End Of
File) cuando se ha alcanzado el final de fichero. Se puede usar la funcin feof() para indagar si
efectivamente el flag se activ.
int i, c;
char buffer[1024];
/* ... Abrir un fichero para lectura usando pf ... */
i = 0;
while(i < 1024 && (c = fgetc(pf)) != EOF ){//Mientras hay espacio en el
//buffer y el flujo entregue
//caracteres
buffer[i++] = (char)c;
//Copiar carcter ledo a arreglo buffer
}
if ( i < 1024 && ! feof(fp) ){
//Si hay espacio en buffer
//y no es fin de fichero, se produjo error
fprintf( stderr, "Error de lectura.\n" );
}

5.1.2
Lavariableerrno
Variasfuncionesdelabibliotecaestndarsoportanmanejodeerroresdeformamsespecfica
estableciendo un valor a la variable global errno para indicar el tipo de error que ha ocurrido.
Algunas funciones de E/S que hacen uso de esta variable incluyen: ftell(), fgetpos(), fsetpos(). La
variable errno est declarada enel fichero de cabeceraerrno.h, en elcual sedefinen macros
conlosposiblesvaloresquepuedetomarestavariable.

Sea el siguiente ejemplo en el que se emplea a la variable errno y a la funcin perror() para
imprimirunmensajeespecficodeerrorhaciaelflujodesalidaestndardeerror(stderr).

//Ejemplo7.c: Uso de errno


#include<stdio.h>
#include<errno.h>
int main(){
FILE *pf = fopen(datos.txt, r);
if(pf != NULL){
long pos = ftell(pf); //Obtener la posicin actual del fichero
if(pos < 0L) //ftell() retorna -1L si ocurri un error
perror(ftell() );
}
}

Lafuncinperror()imprimelacadenaquerecibecomoargumentoseguidopordospuntos,el
mensajedeerroryelcarcterdesaltodelnea.

5.2. E/Ssinformato
La biblioteca estndar de C provee un conjunto de funciones para leer y escribir datos sin
formato ya sea carcter a carcter, como cadena de caracteres o bloque de caracteres de un
tamaodeterminado.Enestaseccindedescribenlasfuncionesmsimportanteparaestetipode
procesamiento.

5.2.1
Lecturadecaracteres
Lassiguientesfuncionesleenuncarcterdesdeunfichero:
int fgetc(FILE *pf);
int getc(FILE *pf);

Lafuncinfgetc()leeuncarcterdelflujodeentradareferenciadoporpf.Elvalorretornadoes
elcarcterledooEOFsiseprodujounerror.Lamacreogetc()tieneelmismoefectoquelafuncin
fgetc().

5.2.2
Devolviendoalflujouncarcterledo
Lasiguientefuncindevuelveuncarcterhaciaelflujodelquefuepreviamenteledo.
int ungetc(int c, FILE *pf);

ungetc()devuelveelltimocarcterledo,c,haciaelflujodeentradareferenciadoporpf.Sise
realiza una nueva lectura del fichero a travs del flujo pf, se leer el carcter que se devolvi al
flujo. Siempre se puede devolver un carcter al flujo, sucesivas intentos (usos de la funcin
ungetc())podranoproducirefecto.

5.2.3
Escribiendocaracteres
Lassiguientesfuncionespermitenescribiruncarcterhaciaelflujo.
9

int fputc(int c, FILE *pf);


int putc(int c, FILE *pf);

Lafuncinfputc()escribeelcarcterchaciaelflujoreferenciaporpf.Elvalorqueretorna
es el carcter escrito o EOF en caso de error. La macro putc() tiene el mismo efecto que la
funcinfputc().

//Ejemplo8.c:Usodefputc.
//EsteejemplocopiaelcontenidodeunficheroabiertoparalecturareferenciadoporpfIn
//haciaunficheroabiertoparaescriturareferenciadoporpfOut.
#include<stdio.h>
int error;
int main(){
int c;
FILE *pfIn = fopen(datos8.txt, r); //Abrir fichero para lectura
FILE *pfOut = fopen(datos_salida.txt, w); //Abrir fichero para escritura
rewind(pfIn);
//Establecer el indicador de posicin al inicio del fichero
while( (c = fgetc(pf)) != EOF ){ //Leer un carcter a la vez
if(fputc(c, pfOut) == EOF){ //Escribir un carcter al flujo de salida
error = 1;
//Se produjo un error de escritura
break;
//Abortar ejecucin de lectura-escritura
}
}
If(ferror(pfIn))
error = 1; //Error de lectura
if(error){
fprintf(stderr, Se produjo un error en la lectura-escritura de fichero);
return 0;
}
}

5.2.4
Lecturadecadenas(strings)
Lasiguientefuncinpermiteleercadenadecaracteresdesdeunflujo:
char *fgets(char *buf, int n, FILE *pf);

Lafuncinfgets()leehastan1caracteresdesdeelflujoreferenciadoporpfyloalmacenaenel
buffer referenciado por buf, agregando un carcter null para terminar la cadena. Si la funcin
encuentra un carcter de nueva lnea o el final de fichero antes de que haya ledo el mximo de
caracteres,entoncessloloscaracteresledoshastaesepuntosonguardadosenbuf.Elcarcter\n
esalmacenadotambinenelbuffersiesledo.

10

5.2.5
Escrituradecadenas(strings)
Lasiguientefuncinesutilizadaparaescribircadenasdecaracteres:
int fputs(const char *s, FILE *pf);

Lafuncinfputs()escribelacadenasenelflujoreferenciadoporpf.Elcarcterdelimitadorde
lacadenanoesescritoenelflujo.

Acontinuacinsemuestraunejemploenelquesebuscaunapalabraenunficherodetexto,sise
encuentra, se copia la lnea en la que se encontr a otro fichero, es decir se hace un filtrado del
contenidodeunfichero.

#include<stdio.h>
#define MAX_LINEA 256
int filtrarFichero(FILE *, FILE *, char *); //Prototipo de la funcin
int main(){
FILE *pfEntrada = fopen(fichero1.txt, r); //Abrir fichero1.txt para lectura
FILE *pfSalida = fopen(fichero2.txt, w); //Abrir fichero2.txt para escritura
if(pfEntrada != NULL && pfSalisa != NULL){ //Se pudieron abrir los ficheros
filtrarFichero(pfEntrada, pfSalida, noche);
fclose(pfEntrada);
fclose(pfSalida);
}
}
int filtrarFichero(FILE *pfEn, FILE *pfSal, char *filtro){
char linea[MAX_LINEA];
//Si pfEn o pfSal o palabra contiene NULL, retornar -1 (no se puede hacer filtrado)
if(pfEn == NULL || pfSal == NULL || filtro == NULL)
return -1;
else
rewind(pfEn); //Sino, ubicar indicador de posicin del fichero al inicio del mismo
while(fgets(linea, MAX_LINEA, pfEn) != NULL){ //Mientras haya lectura de caracteres
//desde el fichero
if(strstr(linea, filtro) != NULL){
//Buscar la palabra a filtrar en la lnea de
//caracteres leda desde el fichero
fputs(linea, pfSal);
//Si se encuentra, copiarla la cadena al
//flujo de salida referenciado por pfSal
}
}
if(!feof(pfEn)){ //Se produjo error de lectura? es decir An no es final de fichero?
return -1;
//retornar -1 indicando error
}
else
//Sino, todo sali bien
return 0; //retornar 0 indicando xito.
}

11

Suponer que en el ejemplo anterior el contenido de fichero1.txt es el que se muestra a


continuacin:
Que para m siempre es de noche,
pero esta noche es como un atardecer,
si logras que a la vida me asome,
tus ojos sean los que brillen.
Yquelapalabraabuscarenelficheroesnoche(comosecodificenelejemplo).
DespusdeejecutarelcdigodelafuncinfiltrarFicheroelcontenidodelficherofichero2.txt
sera:
Que para m siempre es de noche,
pero esta noche es como un atardecer,

5.2.6
Lecturayescrituradebloquededatos
Existen dos funciones, fread() y fwrite(), para leer y escribir, respectivamente, bloques de
datosdesdeohaciaunfichero.Lafuncinfread()cuyasintaxises:
size_t fread(void *buffer, size_t tam, size_t n, FILE *pf);

Seencargadeleerhastanelementoscuyotamaoestamdesdeelflujoreferenciadoporpfylos
almacenaenelarrayreferenciadoporbuffer.Lafuncinretornaelnmerodeelementosledosy
transferidosabuffer.Unvalorderetornomenorqueelargumentonindicaquesehaalcanzadoel
finaldeficherooquehaocurridounerror(retorno0,porejemplo).

Lafuncinfwrite()tienelasiguientesintaxis:
size_t fwrite(const void *buffer, size_t tam, size_t n, FILE *pf);

Lafuncinfwrite()envanelementosdetamaotamdesdeelarregloreferenciadoporbufferhacia
elflujodesalidareferenciadoporpf.Semejantequefread(),elvalorretornadoporfwrite()esel
nmerodeelementosescritos.Unvalormenorqueelargumentonindicaquehaocurridounerror.

Ensistemasoperativosenlosquesehagadistincinentreflujosbinariosytextos,esrecomendable
utilizarlasfuncionesantesdescritosnicamenteparaflujosbinarios.

Elsiguienteejemplocopiaelcontenidodeunficherohaciaotro,perofiltrandoaquellosquetengan
un valor 0 en el campo clave de la estructura declarada. El ejemplo supone que el fichero
registros.datyacontienedatos.

#include<stdio.h>
#include<stdlib.h>
#define ARRAY_LEN
100;
//Declaracin de estructura para registros
typedef struct{
long clave;
char nombre[30];
int edad;

12

} Registro_t;
void mensaje_error(int estado, const char *error_msg);
char ficheroEntrada[ ] = registros.dat;
char ficheroSalida[ ] = registros2.dat;
int main(){
FILE *pfEntrada, *pfSalida;
Registro_t registro, *pRegistro;
unsigned int i;
if((pfEntrada = fopen(ficheroEntrada, rb)) == NULL){ //Abrir fichero para lectura
mensaje_error(1, Error al abrir fichero de entrada);
}
else if((pfSalida = fopen(ficheroSalida), wb) == NULL){ //Abrir fichero para escritura
mensaje_error(2, Error al abrir fichero de salida);
}
//crear el array de registros
else if((pRegistro = (Registro_t *)malloc(sizeof(Registro_t)*ARRAY_LEN)) == NULL){
//Si no se pudo asignar memoria, indicar error
mensaje_error(3, Insuficiente memoria);
}
i = 0;
//Mientras leamos un elemento desde el flujo referenciado por pfEntrada
while(fread(&registro, sizeof(Registro_t), 1, pfEntrada) == 1){
if(registro.clave != 0L){ //No est marcado como borrado?
//entonces copiarlo
pRegistro[i].clave = registro.clave;
strcpy(pRegistro[i].nombre, registro.nombre);
pRegistro[i].edad = registro.edad;
i++;
if( i == ARRAY_LEN){ //Est el array lleno?
//S, est lleno, escribirlo hacia el fichero
if(fwrite(pRegistro, sizeof(Registro_t), i, pfSalida) < i)
break; //Si se escribi menos de lo esperado, salir del ciclo.
i = 0;
}
}
}
if( i > 0){ //Si an hay datos, escribirlos en el fichero
fwrite(pRegistro, sizeof(Registro_t), i, pfSalida);
}
if(ferror(pfSalida))
mensaje_error(4, Error en la escritura del fichero);
else if(ferror(pfEntrada))
mensaje_error(5, Error en la lectcura del fichero);

13

return 0;
}
void mensaje_error(int estado, const char *error_msg){
fputs(error_msg, stderr);
exit(estado);
}

5.3. Entradaysalidaconformato
LabibliotecaestndardeCproveefuncionesparaleeryescribirdatosconformatodesdeyhacia
un fichero. Dichas funciones incluyen a fscanf() y fprintf(), para leer y escribir,
respectivamente.

La funcin fscanf() provee una funcionalidad semejante a la ya conocida funcin scanf() con la
diferenciaqueahoraseleeconformatodesdeunflujodeentradaasociadoaunfichero.Lasintaxis
delafuncines:
int fscanf(FILE *restrict pf, const char *restrict format, );

Lafuncinfprintf()proveelafuncionalidadparaescribirdatosconformatoaunfichero.Lasintaxisde
lafuncinescomosigue:
int fprintf(FILE *restrict pf, constant char *restrict format, );

Esimportantehacernotarquelafuncinfprintf()essimilaralafuncinprintf(),conladiferenciaque
lasalidaserealizasobreunficheroreferenciadoporpf.

6.

Accesoaleatorioaficheros

Elaccesoaficherosdeformaaleatoriaserefierealhechodepoderleeromodificarinformacin
directamente desde una posicin dada en el fichero. Esta capacidad se obtiene estableciendo y
obteniendoelindicadordeposicindelfichero,elcualrepresentalaposicindeaccesoactualenel
ficheroasociadoconunflujodado.

6.1. Obteniendolaposicinactualdelfichero
Lassiguientesfuncionesretornanlaposicinactualdeaccesoalfichero.
long ftell(FILE *pf);

ftell() retorna la posicin del fichero referenciado por el flujo especificado por pf. Para un flujo
binario, se refiere al desplazamiento del carcter actual desde el principio del archivo. En caso de
error,ftell()retorna1.

int fgetpos(FILE *pf, fpost_t *ppos);

Esta funcin escribe la posicin actual del indicador de posicin de fichero referenciado por pf
haciaelobjetoppos,esdecir,enpposseguardarelvalorcorrespondientedelindicadordeposicin
delfichero.Lafuncinretornaunvalordistintodecerosiocurriunerrororetornacerositodosali
bien.

14

Elsiguienteejemploguardalaposicindetodaslaslneasenelficheromensaje.txtqueempiecen
conelcarcter!:

//Ejemplo_ftell.c
#include<stdio.h>
#define MAX_LEN 1000
long arrayPosicion[MAX_LEN] = {0L};
int main(){
FILE *pf = fopen(mensaje.txt, r); //Abrir fichero para lectura
if(pf != NULL){
int i = 0, c = \n, c2;
//Mientras haya espacio en el array y no se alcance final de fichero
//Leer un carcter
while(i < MAX_LEN && (c2 = fgetc(pf)) != EOF){
//Comparar si carcter ledo es !
//Adems se debe cumplir que hay un saldo de lnea previo
//para asegurarnos que estamos al inicio de cada lnea del fichero
if(c == \n && c2 == !){
//Si carcter ledo es !, entonces obtener su posicin
arrayPosicion[i++] = ftell(pf) 1;
}
c = c2;
}
}
}
6.2. Estableciendolaposicindelfichero

Lassiguientesfuncionesmodificanelindicadordeposicindelfichero:

int fsetpos(FILE *pf, const fpost_t *ppos);

Esta funcin obtiene el valor del indicador de posicin del fichero referenciado por pf y lo
guardaenelppos.Lafuncinretorna0ylimpiaelflagdeEOFsituvoxito,encasodeerrorretorna
unvalordistintodecero.

int fseek(FILE *pf, long despl, int origen);

Establece el indicador de posicin del fichero a la posicin especificada por el argumento


despl a partir del punto de referencia indicado por el argumento origen. El argumento despl
indicaunaposicinrelativaaunodetresposiblespuntosdereferencia,especificadospormacros.La
siguientetablamuestralistadelasmacrosylosvalorescorrespondientes.Elvalordedesplpuede
sernegativo,perolaposicinresultantetienequeserigualomayoracero.

15

Macro
SEEK_SET
SEEK_CUR
SEEK_END

Valor
0
1
2

Desplazamientorelativoa
Eliniciodelfichero
Laposicinactualdelfichero
Elfinaldelfichero

Cuandosetrabajeensistemasquedistingaentreflujosbinariosydetextoesimportantesiempre
usarunvalorparaelargumentodesplobtenidoporlainvocacinalafuncinftell()yestablecerel
argumentoorigenalvalordeSEEK_SET.

La funcin retorna cero y limpia elflag EOF si todo sali bien, en caso de error retorna un valor
distintodecero.

void rewind(FILE *pf);

Lafuncinrewind()estableceelindicadordeposicindelficheroaliniciodelmismoylimpialos
flagsdeerroresyEOF.Exceptoporlalimpiezadelflagdeerror,unainvocacinequivalentearewind()
es:
(void)fseek(fp, 0L, SEEK_SET);

Enelsiguienteejemploseilustraelusodealgunasfuncionesanteriormentedescritas.Semuestrauna
funcinenelqueseusaunatabladendicesparaguardarlaposicindeunregistroenelfichero.Esta
ideapermiteaccesodirectoalosregistrosdelficheroquenecesitanseractualizados.

//establecerNombre(): Busca una clave en una tabla ndice


//y actualiza el registro correspondiente en el fichero.
//El fichero que contiene los registros debe ser abierto en modo actualizacin, es decir,
//con el modo r+b.
//Argumentos de la funcin:
//- un puntero a FILE que referencia el fichero de datos.
//- la clave a buscar
//- el nuevo nombre a actualizar
//Valor de retorno: un puntero al registro actualizado o NULL si no se encontr
#include<stdio.h>
#include<string.h>
typedef struct{
long clave;
char nombre[30];
}Registro_t;
typedef struct{
long clave, pos;
}TablaIndice_t;

16

TablaIndice_t tablaIndices[ ];
//La tabla ndice
int longitudIndices;
//Nmero de entradas en la tabla
Registro_t * establecerNombre(FILE *pf, long clave, char *nuevoNombre){
static Registro_t registro;
int i;
for(i = 0; i < longitudIndices; i++){ //Buscar clave en la tabla ndice
if(clave == tablaIndices[i].clave)
break; //Se encontr clave, salir del ciclo for.
}
if(i == longitudIndices)
//Si se recorri toda la tabla y no se encontr, entonces
return NULL;
//retornar NULL
//Establecer la posicin al registro indicado
if(fseek(pf, tablaIndice[i].pos, SEEK_SET) != 0)
return NULL; //Si da error fseek() retornar NULL
//Leer el registro despus de ubicarnos en la posicin indicada antes
if(fread(&registro, sizeof(Registro_t), 1, pf) != 1)
return NULL; //Si da error la lectura, retornar NULL
//Verificar que el registro ledo es el correcto
if(clave != registro.clave)
return NULL; //Si no lo es, retornar NULL
else{
size_t tam = sizeof(registro.nombre)/sizeof(registro.nombre[0]);
strncpy(registro.nombre, nuevoNombre, tam - 1);
registro.nombre[tam - 1] = \0;
//Establecer nuevamente
if(fseek(pf, tablaIndices[i].pos, SEEK_SET) != 0)
return NULL; //retornar NULL si ocurri un error
//Actualizar el registro del fichero con el nuevo valor
if(fwrite(&registro, sizeof(Registro_t), 1, pf) != 1)
return NULL;//retornar NULL si ocurri error de escritura
//Retornar la direccin del registro actualizado
return &registro;
}
}

17

Das könnte Ihnen auch gefallen