Yanıtlar:
Bir dosya tanımlayıcı, Linux ve diğer Unix benzeri sistemlerde çekirdek düzeyinde açık bir dosyayı (veya soketi veya her neyse) tanımlamak için kullanılan düşük seviyeli bir tamsayı "tutamaç" dır.
Aşağıdaki gibi gerçek Unix aramaları için "çıplak" dosya tanımlayıcıları geçmesi read()
, write()
vb.
Bir FILE
gösterici, bir dosya temsil etmek için kullanılan bir Cı standart kütüphane düzeyinde yapıdır. FILE
Dosya tanıtıcı sarar ve I / O kolaylaştırmak için belleğe alma ve diğer özellikler ekler.
Geçtin FILE
gibi standart C işlevlerine işaretçiler fread()
ve fwrite()
.
fd
, ilk argümanın olduğunu söylüyor read()
. Neden çıplak diyorsun?
FILE *
türü ile karşılaştırıldığında, tamsayı dosya tanımlayıcısı "daha az sarmalıdır ", yani "çıplaktır".
Biri tamponlanır ( FILE *
) ve diğeri değildir. Pratikte, FILE *
ne yaptığınızı bilmediğiniz veya dosyanız gerçekten bir soket olmadığı sürece, 'gerçek' bir dosyadan (yani sürücüde) okurken neredeyse her zaman kullanmak istersiniz .
Dosya tanımlayıcısını FILE *
kullanarak alabilir fileno()
ve kullanarak FILE *
bir dosya tanımlayıcısından arabelleğe alınmış bir dosya açabilirsiniz.fdopen()
Bir dosya tanımlayıcı, POSIX open()
çağrısından aldığınız bir tamsayıdır . Standart C'yi kullanarak fopen()
bir FILE
yapı geri alırsınız . FILE
Yapı böyle sonu dosyası vb ve hata göstergesi, dere pozisyonu olarak diğer şeyler arasında bu dosya tanıtıcı içeriyor
Yani kullanmak fopen()
size ile karşılaştırıldığında belirli bir miktar soyutlama sağlar open()
. Genel olarak fopen()
, daha taşınabilir olduğu için kullanmalısınız ve FILE
struct yani fprintf()
ve ailesini kullanan diğer tüm standart C işlevlerini kullanabilirsiniz .
İkisini de kullanan hiçbir performans sorunu yok.
Dosya tanımlayıcı ve Dosya işaretçisi
Dosya tanımlayıcı:
Dosya Tanımlayıcı, open()
sistem çağrısı tarafından döndürülen bir tamsayı değeridir .
int fd = open (filePath, mode);
Dosya işaretçisi:
Dosya İşaretçisi, bir dosyayı tanımlamak, dosya tanımlayıcısını sarmak, arabelleğe alma işlevi ve G / Ç işlemi için gereken diğer tüm işlevleri sağlamak içinfopen()
kullanılan kitaplık işlevi tarafından döndürülen bir C yapısına işaretçidir. Dosya işaretçisi, tanımı olan FILE türündedir. "/usr/include/stdio.h" içinde bulunabilir . Bu tanım, bir derleyiciden diğerine değişebilir.
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;
Yararlı olabilecek noktalar eklemek ister.
HAKKINDA FILE *
Hata ayıklama günlükleri için birçok kez kullanıyorum. misal,
FILE *fp;
fp = fopen("debug.txt","a");
fprintf(fp,"I have reached till this point");
fclose(fp);
HAKKINDA FILE DESCRIPTOR
Genellikle IPC için kullanılır.
* Nix sistemlerindeki dosyalara (aygıtlar, dosyalar, soketler, vb.) Düşük seviyeli kontrol verir, bu nedenle FILE *
.
fdopen()
IPC ve cihazlar gibi şeyler yapmak için kullanamaz FILE*
mısın?
FILE*
, ancak FILE*
bir dosya tanımlayıcıdan ( fdopen()
) bir oluşturabilir ve daha sonra kapatıldığında FILE
tanımlayıcı da kapanacaktır. Bu nedenle, olabilir yapmak IPC, ancak herhangi bir doğrudan IPC kolaylaştırmak için biraz dosya tanıtıcısı uğraşmak zorunda.
FILE *
Eğer API işlevlerini gibi kullanmanıza olanak sağlar, çünkü metin dosyaları ve kullanıcı giriş / çıkışı ile çalışırken daha yararlıdır sprintf()
, sscanf()
, fgets()
, feof()
vb
Dosya tanımlayıcı API'si düşük seviyelidir, bu nedenle soketler, borular, bellek eşlemeli dosyalarla (ve tabii ki normal dosyalarla) çalışmaya izin verir.
Tartışmayı bitirmek için sadece bir not (ilgileniyorsanız) ....
fopen
güvensiz olabilir ve muhtemelen fopen_s
veya open
özel bit kümesiyle kullanmanız gerekir . C1x sunuyor x
böylece yapabilirsiniz, modları fopen
modları ile "rx"
, "wx"
vb
Kullanırsanız open
, open(..., O_EXCL | O_RDONLY,... )
veya düşünebilirsiniz open(..., O_CREAT | O_EXCL | O_WRONLY,... )
.
Örneğin, bkz. Fopen () ve dosya oluşturma hakkında varsayımlarda bulunmayın .
fopen_s
ile kullanılabilir olması için görünmüyor POSIX
, ben en taşınabilir soultion olacaktır varsayalım open(2)
ve daha sonra fdopen(2)
. (pencereleri bir kenara bırakarak). Ayrıca, hangisi daha hızlı fopen_s()
veya daha open(2)
sonra olur fdopen(2)
?
Sistem çağrıları çoğunlukla dosya tanımlayıcı kullanır, örneğin read
ve write
. Kitaplık işlevi dosya işaretleyicilerini ( printf
, scanf
) kullanacaktır . Ancak, kütüphane işlevleri yalnızca dahili sistem çağrılarını kullanır.
Burada , ikisi arasındaki farklara yüksek düzeyde genel bakış sağlayan iyi bir kaynak buldum :
Bir dosyaya giriş veya çıkış yapmak istediğinizde, programınız ile dosya arasındaki bağlantıyı temsil etmek için iki temel mekanizma seçeneğiniz vardır: dosya tanımlayıcıları ve akışlar. Dosya tanımlayıcıları int türünde nesneler olarak temsil edilirken, akışlar FILE * nesneleri olarak temsil edilir.
Dosya tanımlayıcıları, giriş ve çıkış işlemleri için ilkel, düşük seviyeli bir arayüz sağlar. Hem dosya tanımlayıcıları hem de akışlar, bir cihaza (terminal gibi) veya başka bir işlemle ve normal bir dosyayla iletişim kurmak için bir boru veya sokete olan bağlantıyı temsil edebilir. Ancak, belirli bir tür aygıta özgü kontrol işlemleri yapmak istiyorsanız, bir dosya tanımlayıcı kullanmanız gerekir; dereleri bu şekilde kullanacak tesis bulunmamaktadır. Ayrıca, programınızın engellemesiz (veya sorgulamalı) girdi gibi özel modlarda girdi veya çıktı yapması gerekiyorsa dosya tanımlayıcıları kullanmanız gerekir (bkz. Dosya Durum Bayrakları).
Akışlar, ilkel dosya tanımlayıcı özelliklerinin üzerine katman olarak yerleştirilmiş daha yüksek düzeyde bir arabirim sağlar. Akış arabirimi her tür dosyayı hemen hemen aynı şekilde ele alır - tek istisna, seçebileceğiniz üç arabelleğe alma stilidir (bkz. Akış Tamponlama).
Akış arayüzünü kullanmanın temel avantajı, akışlar üzerinde gerçek girdi ve çıktı işlemlerini (kontrol işlemlerinin aksine) gerçekleştirmek için işlevler kümesinin, dosya tanımlayıcılar için karşılık gelen olanaklardan çok daha zengin ve daha güçlü olmasıdır. Dosya tanımlayıcı arabirimi, karakter bloklarını aktarmak için yalnızca basit işlevler sağlar, ancak akış arabirimi ayrıca güçlü biçimlendirilmiş girdi ve çıktı işlevleri (printf ve scanf) ile karakter ve satır yönelimli girdi ve çıktı işlevleri sağlar.
Akışlar dosya tanımlayıcıları açısından uygulandığından, dosya tanımlayıcısını bir akıştan çıkarabilir ve düşük düzeyli işlemleri doğrudan dosya tanımlayıcı üzerinde gerçekleştirebilirsiniz. Ayrıca başlangıçta bir dosya tanımlayıcısı olarak bir bağlantı açabilir ve ardından bu dosya tanımlayıcısıyla ilişkilendirilmiş bir akış oluşturabilirsiniz.
Genel olarak, yalnızca bir dosya tanımlayıcı üzerinde yapılabilen, yapmak istediğiniz belirli bir işlem olmadıkça, dosya tanımlayıcıları yerine akışları kullanmaya devam etmelisiniz. Başlangıç programcısıysanız ve hangi işlevleri kullanacağınızdan emin değilseniz, biçimlendirilmiş girdi işlevlerine (Biçimlendirilmiş Girdi'ye bakın) ve biçimlendirilmiş çıktı işlevlerine (Biçimlendirilmiş Çıktı'ya bakın) odaklanmanızı öneririz.
Programlarınızın GNU dışındaki sistemlere taşınabilirliği konusunda endişeleriniz varsa, dosya tanımlayıcılarının akışlar kadar taşınabilir olmadığını da bilmelisiniz. ISO C çalıştıran herhangi bir sistemin akışları desteklemesini bekleyebilirsiniz, ancak GNU olmayan sistemler dosya tanımlayıcıları hiç desteklemeyebilir veya dosya tanımlayıcıları üzerinde çalışan GNU işlevlerinin yalnızca bir alt kümesini uygulayabilir. Bununla birlikte, GNU C Kitaplığındaki dosya tanımlayıcı işlevlerinin çoğu POSIX.1 standardına dahil edilmiştir.