Funciones Unix
de Archivos
open
$ man 2 open
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
flags: O_RDONLY, O_WRONLY & O_RDWR
mode: O_APPEND, O_CREAT, O_TRUNC, más...
close
$ man 2 close
#include <unistd.h>
int close(int fd);
read
$ man 2 read
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
write
$ man 2 write
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
lseek
$ man 2 lseek
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
whence: SEEK_SET, SEEK_CUR & SEEK_END
fcntl
$ man 2 fcntl
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
cmd: F_DUPFD - Duplicating a file descriptor (y otros...)
Tamaño Archivo
Se podría usar lseek, pero tiene un int como tamaño.
#include <stdio.h>
#include <sys/stat.h>
int main() {
char filename[] = "somefile.txt";
struct stat st;
stat(filename, &st);
off_t size = st.st_size;
printf("The file size id %d bytes.\n", size);
return 0;
}
FILE *fopen(const char *filename, const char *mode);
(I)
- Abriendo Archivos
- Antes de leer o escribir debemos abrir los archivos y conseguir el descriptor del archivo a usar.
- Retorna:
- Si exitoso el puntero al descriptor del nuevo archivo.
- Si hay error un puntero nulo
- Modos de apertura:
- r: Solo lectura
- w: Solo escritura
FILE *fopen(const char *filename, const char *mode);
(II)
- a: Escritura al final del archivo o creado para escritura si no existia
- r+: Abre un archivo para ser actualizado (lectura y escritura)
- w+: Abre un archivo para lectura y escritura, pero si existia el archivo lo "pisa" (borra)
- a+: Similar al modo "a", pero desplaza el puntero hasta el final del archivo
Modo Binario o Texto:
- Si se agrega una "b" al final (p/ej rb) C los interpreta como binarios.
- Esto solo tiene sentido si la aplicación debe manejar archivos de windows y unix que tienen diferencias de formato en modo texto que C manejará por defecto e ignorará si usamos el modificador b.
int fclose(FILE *stream);
int feof(FILE *stream);
- fclose() - Cerrando un archivo
- feof() - ¿Estamos en el fin del archivo?
- Retorna algo distinto de 0 (verdadero) si el puntero dentro del archivo llegó al final.
- Retorna 0 si el archivo todavía tiene datos.
int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
- fgetc()/fputc():
- Si exitoso retorna el carácter leído o escrito convertido (casteado) a un entero.
- Si falla o llega al final del archivo retornará EOF
Archivo usado en el ejemplo miarch.txt
#include <stdio.h>
int main()
{
FILE *file = fopen("miarch.txt", "r");
int x;
/* Lee un caracter en cada pasada desde el archivo terminando */
/* cuando encuentra EOF. */
while (( x = fgetc(file)) != EOF ) {
printf( "%c", x );
}
fclose( file );
}
int fscanf (FILE *stream,
const char *format [, address, ...]);
int fprintf (FILE *stream,
const char *format [, argument, ...]);
- Descripción:
- Son las funciones de entrada y salida formateada, pero se pueden aplicar directamente a archivos
- fscanf() retorna:
- Si exitoso el numero de campos de entrada que pudo tomar, convertir y guardar.
- Si retorna 0 es por que ningún campo pudo ser guardado
- Si se llegó al final del archivo retornará EOF
- fprintf() retorna:
- Si exitoso en numero de bytes que pudo mostrar
- Si hay error retornará EOF
#include <stdio.h>
int main()
{
FILE *file = fopen("miarch.txt", "r");
FILE *file2 = fopen("miarchout.txt", "w");
int x;
while (( x = fgetc(file)) != EOF ) {
//printf( "%c", x );
//fputc(x,file2);
fprintf(file2,"%x ",(char) x);
}
fclose( file );
fclose( file2 );
}
Otro ejemplo que
imprime en hexa: ej1_v3.c
char *fgets(char *s, int size, FILE *stream);
int fputs(const char *s, FILE *stream);
- fgets():
- Exitoso: El puntero al string s
- Error o fin del archivo: NULL
- fputs():
- Si fue exitoso retorna un número positivo
- Si falla retornará EOF
#include <stdio.h>
int main()
{
FILE *fp;
char str[60];
fp = fopen("file.txt" , "r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
}
if( fgets (str, 60, fp)!=NULL ) {
puts(str);
}
fclose(fp);
return(0);
}
Nota: El "if" no itera. El ej2_2.c es una versión con número de línea y que itera.
size_t fread(void *ptr, size_t size, size_t n,
FILE *stream);
size_t fwrite(const void *ptr, size_t size,
size_t n, FILE *stream);
(I)
- Los argumentos:
- ptr: Puntero al bloque de datos a leer o escribir
(Recordar que "void *" es... ¡Casting!)
- size: Tamaño de cada elemento a leer o escribir en bytes
- n: Cantidad de elementos a leer
- stream: Descriptor del archivo a leer o escribir
- size_t: En este caso es la cantidad de elementos
size_t fread(void *ptr, size_t size, size_t n,
FILE *stream);
size_t fwrite(const void *ptr, size_t size,
size_t n, FILE *stream);
(II)
- fread(): Leyendo datos de un archivo
- Retorna:
- Si es exitoso: La cantidad de elementos leídos
- Si hay error EOF o 0 (elementos leídos)
- fwrite(): Escribiendo datos a un archivo
- Retorna:
- Si es exitoso: La cantidad de elementos que pudo escribir
- En error retorna un número mas bajo del solicitado o cero.
¿Como dejo de usar scanf()
para probar ejercicios?
- ej5w.c: leo un archivo de texto,
y escribo uno de datos.
- ej5r.c: leo un archivo de datos.
Nota: Para el ejercicio usar el archivo de ejemplo misnum.txt
Flujos / Streams
- Concepto de flujo de datos:
- Tipos de stream conocidos:
- stdin: Entrada estándar
- stdout: Salida estándar
- stderr: Error estándar
long ftell(FILE *stream);
- ftell():
- Retorna la posición actual en el archivo
- Si el archivo es binario se calcula el desplazamiento en bytes desde el principio del archivo
- El valor retornado por ftell() puede ser usado luego en llamados a fseek().
- Retorna:
- Si exitoso la posición dentro del archivo
- Si hubo un error retorna un -1L (valor negativo)
void rewind(FILE *stream);
- rewind():
- Al terminar rewind() el archivo comenzará a leer o escribir al principio del archivo.
- Es el equivalente de fseek(stream, 0L, SEEK_SET), pero también limpia los flag de EOF y error. fseek() solo limpia el flag de EOF.
int fseek(FILE *stream, long offset, int whence);
(I)
- Mueve la posición dentro del archivo (modificando el descriptor de archivo).
- Argumentos
- stream: Descriptor del archivo al cual le queremos modificar la posición de lectura/escritura.
- offset: Desplazamiento. Diferencia en bytes hacia la nueva posición. Si queremos saber donde ir podemos averiguarlo usando ftell() y movernos desde SEEK_SET.
- whence: Uno de las tres posiciones (SEEK_xxx) desde donde desplazarnos definidas (0, 1, or 2)
int fseek(FILE *stream, long offset, int whence);
(II)
- Retorna:
- 0 si el movimiento se pudo hacer
- Un valor distinto de 0
- SEEK_xxx (define donde se comienza a moverse)
- SEEK_SET (0) comienza al principio del archivo
- SEEK_CUR (1) comienza a moverse desde la posición actual
- SEEK_END (2) comienza el movimiento desde el final del archivo
Ejercicio
Calcular el tamaño del archivo: miarch.txt
Nota: Tienen algo así en una parte del ejemplo de copia de archivos (ej6.c).
int fgetpos(FILE *stream, fpos_t *pos);
int fsetpos(FILE *stream, fpos_t *pos);
(I)
- Las funciones fgetpos() y fsetpos() trabajan en conjunto y permiten moverse por el archivo.
- Son alternativas al uso de ftell() y fseek() (cuando usamos "whence" como SEEK_SET).
-
Uso:
- Con fgetpos() obtendremos la posición actual
- Con fsetpos() la modificaremos
int fgetpos(FILE *stream, fpos_t *pos);
int fsetpos(FILE *stream, fpos_t *pos);
(II)
fpos_t: Tipo de dato dependiente de la implementación del compilador
- DJGPP: typedef unsigned long fpos_t;
- Borland & Dev-C++: typedef long fpos_t;
- No está definido de manera cierta en Unix
Lo mejor es solo usar fpos_t entre ambas funciones,
ya que no se puede asegurar la portabilidad del dato.
funciones similares
fgetc(stdin); === getc();
fputc(stdout); === putc();
fprintf(stdout, ...); === printf(...);
fscanf(stdin, ...); === scanf(...);
ftell() === fgetpos()
fseek() === fsetpos()