Bir dosya tanımlayıcı ile dosya tanıtıcısı arasındaki fark nedir?


Yanıtlar:


144

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 FILEgösterici, bir dosya temsil etmek için kullanılan bir Cı standart kütüphane düzeyinde yapıdır. FILEDosya tanıtıcı sarar ve I / O kolaylaştırmak için belleğe alma ve diğer özellikler ekler.

Geçtin FILEgibi standart C işlevlerine işaretçiler fread()ve fwrite().


@nvl: fildes kesinlikle Windows'ta kullanılabilir, örneğin msdn.microsoft.com/en-us/library/z0kc8e3z%28VS.80%29.aspx
kennytm

2
@unwind "Çıplak" dosya tanımlayıcılarla ne demek istediniz? Bağlantılı referans fd, ilk argümanın olduğunu söylüyor read(). Neden çıplak diyorsun?
Geek

3
@Geek Standart kitaplığın FILE *türü ile karşılaştırıldığında, tamsayı dosya tanımlayıcısı "daha az sarmalıdır ", yani "çıplaktır".
gevşeyin

57

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()


12
Fileno () 'yu işaret eden +1, man sayfalarının düzenlenmesi bunu bulmayı zorlaştırıyor. Fdopen () için aynı.
Rivenhill'de BD

20

Bir dosya tanımlayıcı, POSIX open()çağrısından aldığınız bir tamsayıdır . Standart C'yi kullanarak fopen()bir FILEyapı geri alırsınız . FILEYapı 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 FILEstruct yani fprintf()ve ailesini kullanan diğer tüm standart C işlevlerini kullanabilirsiniz .

İkisini de kullanan hiçbir performans sorunu yok.


8
Taşınabilirliği artırmak için +1. FILE, Standart C Kitaplığının bir parçasıdır (C89 / C90'a geri); dosya tanımlayıcıları değildir.
tomlogic

15

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);

  1. Düşük / Çekirdek seviyesi işleyici.
  2. UNIX Sistem Çağrılarını okumak () ve yazmak () için passe.
  3. Arabelleğe alma ve bu tür özellikleri içermez.
  4. Daha az taşınabilir ve verimsiz.

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;
  1. Üst düzey arayüzdür.
  2. Fread () ve fwrite () işlevlerine geçti.
  3. Arabelleğe alma, hata göstergesi ve EOF algılama, vb. İçerir.
  4. Daha yüksek taşınabilirlik ve verimlilik sağlar.

1
Bu yüksek verimlilik iddiasını destekleyebiliyor musunuz? Bunu hiç duymadım.
Gid

1
"Verimlilik" iddiası arabelleğe alma nedeniyle olabilir. Bir dosya tanımlayıcıyla, her okuma () veya yazma () bir sistem çağrısıdır ve her sistem çağrısının pahalı olduğu düşünülmelidir. FILE * ile arabelleğe alma, bazı okuma ve yazma işlemlerinin sistem çağrısı olmayacağı anlamına gelir.
Mike Spear

12

Yararlı olabilecek noktalar eklemek ister.

HAKKINDA FILE *

  1. işlemler arası iletişim (IPC) için kullanılamaz.
  2. genel amaçlı tamponlu G / Ç'ye ihtiyacınız olduğunda kullanın. (printf, frpintf, snprintf, scanf)
  3. 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

  1. Genellikle IPC için kullanılır.

  2. * 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?
osvein

Aslında hem evet hem hayır. IPC'yi ile kurup başlatamazsınız FILE*, ancak FILE*bir dosya tanımlayıcıdan ( fdopen()) bir oluşturabilir ve daha sonra kapatıldığında FILEtanı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.
Micah W

3

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.


1
+1, çünkü bellek eşlemeli dosyalar eklediniz, çünkü şu anki okumamdan itibaren diğer yanıtlar zaten sağlandı.
ernie.cordell

3

Tartışmayı bitirmek için sadece bir not (ilgileniyorsanız) ....

fopengüvensiz olabilir ve muhtemelen fopen_sveya openözel bit kümesiyle kullanmanız gerekir . C1x sunuyor xböylece yapabilirsiniz, modları fopenmodları 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 .


As fopen_sile 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)?
Mihir

1

Sistem çağrıları çoğunlukla dosya tanımlayıcı kullanır, örneğin readve 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.


Kütüphane işlevlerinin yalnızca dahili sistem çağrılarını kullandığını neden söylediğinizden emin değilim: Standart CI / O (veya bu konuda başka herhangi bir) işlevini kastediyorsanız, bunun (evrensel olarak?) Doğru olduğundan emin değilim. Aksi takdirde, söylediğin bu değildi, bu yüzden postandaki dilin biraz temizlendiğini görmek isterim. Son cümle beni şaşırtıyor.
ernie.cordell

1

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.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.