Respuestas:
Un descriptor de archivo es un "identificador" entero de bajo nivel que se usa para identificar un archivo abierto (o socket, o lo que sea) a nivel del kernel, en Linux y otros sistemas similares a Unix.
Pasa descriptores de archivos "desnudos" a llamadas Unix reales, como read()
, write()
etc.
Un FILE
puntero es una construcción de nivel de biblioteca estándar de C, que se utiliza para representar un archivo. La FILE
envuelve el descriptor de archivo y añade tampón y otras características para hacer de E / S más fácil.
Pasa FILE
punteros a funciones C estándar como fread()
y fwrite()
.
fd
es el primer argumento de read()
. ¿Por qué lo llamas desnudo?
FILE *
tipo de biblioteca estándar , el descriptor de archivo entero está "menos envuelto", es decir, "desnudo".
Uno está almacenado en búfer ( FILE *
) y el otro no. En la práctica, querrá usar FILE *
casi siempre cuando esté leyendo de un archivo 'real' (es decir, en la unidad), a menos que sepa lo que está haciendo o que su archivo sea en realidad un socket o algo así.
Puede obtener el descriptor de archivo FILE *
usando fileno()
y puede abrir un búfer FILE *
desde un descriptor de archivo usandofdopen()
Un descriptor de archivo es solo un número entero que se obtiene de la open()
llamada POSIX . Usando el estándar C fopen()
obtienes una FILE
estructura. La FILE
estructura contiene este descriptor de archivo, entre otras cosas, como el indicador de fin de archivo y error, la posición de la secuencia, etc.
Por lo tanto, usar fopen()
le brinda una cierta cantidad de abstracción en comparación con open()
. En general, debería usarlo, fopen()
ya que es más portátil y puede usar todas las demás funciones estándar de C que usan la FILE
estructura, es decir, fprintf()
y la familia.
No hay problemas de rendimiento al usar ninguno.
Descriptor de archivo vs puntero de archivo
Descriptor de archivo:
El descriptor de archivo es un valor entero devuelto por una open()
llamada al sistema.
int fd = open (filePath, mode);
Puntero de archivo:
File Pointer es un puntero a una estructura C devuelta por la fopen()
función de biblioteca, que se utiliza para identificar un archivo, envolver el descriptor de archivo, la funcionalidad de almacenamiento en búfer y todas las demás funciones necesarias para la operación de E / S. El puntero de archivo es de tipo FILE , cuya definición se puede encontrar en "/usr/include/stdio.h" . Esta definición puede variar de un compilador a otro.
FILE *fp = fopen (filePath, mode);
// A FILE Structure returned by fopen
typedef struct
{
unsigned char *_ptr;
int _cnt;
unsigned char *_base;
unsigned char *_bufendp;
short _flag;
short _file;
int __stdioid;
char *__newbase;
#ifdef _THREAD_SAFE
void *_lock;
#else
long _unused[1];
#endif
#ifdef __64BIT__
long _unused1[4];
#endif /* __64BIT__ */
} FILE;
Quiere agregar puntos que puedan ser útiles.
ACERCA DE FILE *
Lo uso muchas veces para depurar registros. ejemplo,
FILE *fp;
fp = fopen("debug.txt","a");
fprintf(fp,"I have reached till this point");
fclose(fp);
ACERCA DE FILE DESCRIPTOR
Generalmente se usa para IPC.
Da control de bajo nivel a archivos en sistemas * nix (dispositivos, archivos, sockets, etc.), por lo que es más poderoso que el FILE *
.
fdopen()
para hacer cosas como IPC y dispositivos con FILE*
?
FILE*
, pero puede crear un FILE*
descriptor de archivo ( fdopen()
) y luego cerrarlo FILE
también cerrará el descriptor. Por lo tanto, puede hacer IPC, pero debe lidiar un poco con los descriptores de archivos para facilitar cualquier IPC directo.
FILE *
es más útil cuando se trabaja con archivos de texto y de usuario de entrada / salida, ya que permite el uso de funciones de la API como sprintf()
, sscanf()
, fgets()
, feof()
etc.
La API del descriptor de archivos es de bajo nivel, por lo que permite trabajar con sockets, tuberías, archivos mapeados en memoria (y archivos normales, por supuesto).
Solo una nota para terminar la discusión (si está interesado) ....
fopen
puede ser inseguro, y probablemente debería usar fopen_s
o open
con bits exclusivos establecidos. C1X está ofreciendo x
modos, por lo que puede fopen
con los modos "rx"
, "wx"
, etc.
Si usa open
, podría considerar open(..., O_EXCL | O_RDONLY,... )
o open(..., O_CREAT | O_EXCL | O_WRONLY,... )
.
Consulte, por ejemplo, No haga suposiciones sobre fopen () y la creación de archivos .
fopen_s
no parece estar disponible con POSIX
, supongo que el soultion más portátil sería open(2)
y luego fdopen(2)
. (dejando las ventanas a un lado). Además, ¿qué sería más rápido fopen_s()
o open(2)
seguido fdopen(2)
?
Las llamadas al sistema utilizan principalmente descriptores de archivos, por ejemplo read
y write
. La función de biblioteca utilizará los punteros de archivo ( printf
, scanf
). Pero, las funciones de la biblioteca solo utilizan llamadas internas al sistema.
Encontré un buen recurso aquí , que brinda una descripción general de alto nivel de las diferencias entre los dos:
Cuando desee hacer entrada o salida a un archivo, tiene la opción de dos mecanismos básicos para representar la conexión entre su programa y el archivo: descriptores de archivo y flujos. Los descriptores de archivo se representan como objetos de tipo int, mientras que los flujos se representan como objetos FILE *.
Los descriptores de archivo proporcionan una interfaz primitiva de bajo nivel para las operaciones de entrada y salida. Tanto los descriptores de archivos como los flujos pueden representar una conexión a un dispositivo (como un terminal), o una tubería o un enchufe para comunicarse con otro proceso, así como un archivo normal. Pero, si desea realizar operaciones de control que sean específicas de un tipo particular de dispositivo, debe usar un descriptor de archivo; no hay facilidades para usar streams de esta manera. También debe utilizar descriptores de archivo si su programa necesita realizar entrada o salida en modos especiales, como entrada sin bloqueo (o sondeo) (consulte las banderas de estado de archivo).
Los flujos proporcionan una interfaz de nivel superior, superpuesta a las funciones de descriptor de archivos primitivos. La interfaz de transmisión trata todo tipo de archivos de manera muy similar, con la única excepción de los tres estilos de almacenamiento en búfer que puede elegir (consulte Almacenamiento en búfer de transmisión).
La principal ventaja de usar la interfaz de flujo es que el conjunto de funciones para realizar operaciones de entrada y salida reales (a diferencia de las operaciones de control) en los flujos es mucho más rico y más poderoso que las funciones correspondientes para descriptores de archivos. La interfaz de descriptor de archivos proporciona solo funciones simples para transferir bloques de caracteres, pero la interfaz de flujo también proporciona potentes funciones de entrada y salida formateadas (printf y scanf), así como funciones para entrada y salida orientadas a caracteres y líneas.
Dado que los flujos se implementan en términos de descriptores de archivo, puede extraer el descriptor de archivo de un flujo y realizar operaciones de bajo nivel directamente en el descriptor de archivo. También puede abrir inicialmente una conexión como un descriptor de archivo y luego hacer una secuencia asociada con ese descriptor de archivo.
En general, debe seguir usando secuencias en lugar de descriptores de archivo, a menos que desee realizar alguna operación específica que solo se pueda realizar en un descriptor de archivo. Si es un programador principiante y no está seguro de qué funciones utilizar, le sugerimos que se concentre en las funciones de entrada formateadas (consulte Entrada formateada) y las funciones de salida formateada (consulte Salida formateada).
Si le preocupa la portabilidad de sus programas a sistemas distintos de GNU, también debe tener en cuenta que los descriptores de archivos no son tan portátiles como los flujos. Puede esperar que cualquier sistema que ejecute ISO C admita transmisiones, pero los sistemas que no son GNU pueden no admitir descriptores de archivo en absoluto, o pueden implementar solo un subconjunto de las funciones GNU que operan en descriptores de archivo. Sin embargo, la mayoría de las funciones de descriptor de archivos de la biblioteca GNU C están incluidas en el estándar POSIX.1.