C fopen vs açık


219

Kullanmak istediğiniz herhangi bir neden var mı (sözdizimsel olanlar dışında)

FILE *fdopen(int fd, const char *mode);

veya

FILE *fopen(const char *path, const char *mode);

onun yerine

int open(const char *pathname, int flags, mode_t mode);

Linux ortamında C kullanırken?


Şunu mu demek istediniz fdopenve openya fopenve open?
user7116

Şunu mu demek istedin fopen, fdopen değil mi?
şeye kadir

9
fopenstandart C kütüphanesinin bir parçasıdır open, değildir. fopenTaşınabilir kod yazarken kullanın .
Aziz

Evet, fopen demek istedim. Sadece güncelledim, ama aynı prensip için geçerli olduğunu düşünüyorum.
LJM

6
@Aziz, openbir POSIX işlevidir.
dreamlax

Yanıtlar:


243

İlk olarak, fdopeneğer fopenbir seçenek ve opendiğer olası seçenek ise kullanmak için özellikle iyi bir neden yoktur . İsterseniz open, dosyayı ilk etapta açmamalısınız FILE *. Bu fdopenlisteye dahil etmek yanlış ve kafa karıştırıcıdır çünkü diğerleri gibi değildir. Şimdi görmezden gelmeye devam edeceğim, çünkü buradaki önemli fark bir C standardı FILE *ile OS'ye özgü bir dosya tanımlayıcı arasında.

fopenBunun yerine dört ana neden vardır open.

  1. fopensize yaptığınızdan çok daha hızlı olabilen tamponlama G / Ç sağlar open.
  2. fopen dosya ikili modda açılmazsa satır sonu çevirisini yapar, bu da programınız Unix olmayan bir ortama taşınmışsa çok yararlı olabilir (dünya yalnızca LF'de yakınsa da görünmektedir (IETF metin tabanlı ağ dışında) SMTP ve HTTP gibi protokoller).
  3. A FILE *size kullanım fscanfve diğer stdio fonksiyonlarını verir.
  4. Kodunuzun bir gün yalnızca ANSI C'yi destekleyen ve openişlevi desteklemeyen başka bir platforma taşınması gerekebilir .

Bence çeviriyi bitiren çizgi size yardımcı olmaktan daha sık yol alır ve ayrıştırma fscanfo kadar zayıftır ki, kaçınılmaz olarak daha yararlı bir şey lehine savurmanız gerekir.

Ve C'yi destekleyen çoğu platformda open işlevi vardır.

Arabelleğe alma sorusu kalmıyor. Çoğunlukla sırayla bir dosyayı okuduğunuz veya yazdığınız yerlerde, arabelleğe alma desteği gerçekten yararlı ve büyük bir hız iyileştirmesi. Ancak, verilerin orada olmasını beklediğinizde dosyada bulunmadığı bazı ilginç sorunlara yol açabilir. Hatırlamak zorundasınfclosefflushUygun zamanlarda veya uygun zamanlarda .

Arama yapıyorsanız (aka fsetposveyafseek ikincisi standartlara uygun bir şekilde kullanmak biraz daha zor), arabelleğe almanın kullanışlılığı hızla azalır.

Tabii ki, önyargım, soketlerle çok fazla çalışma eğiliminde olduğum ve gerçekten FILE *ve hiç tamponlama olmadan hiç engellemeyen IO ( tamamen makul bir şekilde destekleyemeyen) yapmak istediğiniz gerçeği var. karmaşık ayrıştırma gereksinimleri gerçekten benim algılarımı renklendirmek.


4
Deneyimlerinizi sorgulamayacağım, ama bununla ilgili biraz ayrıntı verdiğinizi duymak isterim. Yerleşik arabelleğin ne tür uygulamalar için yol aldığını düşünüyorsunuz? Sorun tam olarak nedir?
Emil H

1
Son paragrafı görmedim. Geçerli nokta, IMHO. Bence soru, IO dosyası hakkındaydı.
Emil H

7
Arabelleğe alma ne zaman engel olur. Arama'yı kullandığınızda. Ne olursa olsun komutuyla aşağıdaki okuma ( fgets, fgetc, fscanf,fread ), her zaman tampon (ayarladığınız her ne 4K, 8K ya) boyutunu tam olarak okuyacaktır. Doğrudan I / O kullanarak bunu önleyebilirsiniz. Bu durumda pread, bir arama / okuma çifti (2 yerine 1 sistem çağrısı) yerine kullanmak daha da iyidir .
Patrick Schlüter

2
Kesilen aramaları read()ve write()çağrıları ele almak , libc fonksiyon ailesini kullanmak için uygun bir beşinci nedendir.
nccc

3
@ m-ric: Bu biraz ilgisiz bir soru, ama evet. Destekleyen tüm platformlar ioctl, filenoçağrıda FILE *kullanılabilen bir numarayı alıp döndüren çağrıyı da destekler ioctl. Yine de dikkatli olun. FILE *ilgili çağrılar ioctl, temeldeki dosya tanımlayıcıyla ilgili bir şeyi değiştirmek için kullanarak şaşırtıcı bir şekilde etkileşime girebilir .
şeye kadir

53

open()düşük seviyeli işletim sistemi çağrısıdır. fdopen()os-seviyesi dosya tanımlayıcısını C dilinin daha yüksek seviye FILE-soyutlamasına dönüştürür. fopen()aramalaropen()arka planda ve doğrudan bir DOSYA işaretçisi verir.

FILE nesnelerini kullanmanın, daha büyük kullanım kolaylığı ve aynı zamanda yerleşik tamponlama gibi diğer teknik avantajları içeren ham dosya tanımlayıcılarını kullanmanın çeşitli avantajları vardır. Özellikle tamponlama genellikle büyük bir performans avantajı sağlar.


3
Açık tamponlu 'f ...' versiyonlarını kullanmanın herhangi bir dezavantajı var mı?
LJM

5
@L. Moser, evet, zaten verileri arabelleğe alırken ve bu nedenle ek tampon gereksiz kopyalama ve bellek ek yükü ekler.
Michael Aaron Safyan

6
aslında başka dezavantajları da var. fopen()dosyaları açarken aynı denetim düzeyini sağlamaz; örneğin izinler oluşturma, paylaşım modları ve daha fazlası. tipik olarak open()ve varyantlar, işletim sisteminin gerçekte sağladığı şeye yakın, çok daha fazla kontrol sağlar
Matt Joiner

2
Ayrıca mmapdosya ve normal I / O ile değişiklikler yaptığımız aşırı durumlar da var (kulağa inanılmaz geliyor, aslında projemizde ve gerçekten iyi nedenlerle yaptığımız gibi), tamponlama yolunda olacak.
Patrick Schlüter

Ayrıca, dosyaları readahead () aracılığıyla sayfa önbelleğine önceden yüklemek için open () kullanmak gibi diğer sistem işlevlerini de kullanmak isteyebilirsiniz. Sanırım başparmak kuralı "kesinlikle open () gerekmedikçe fopen kullanın", open () aslında süslü şeyler (O_ATIME ve benzeri ayar / ayar değil) yapmanızı sağlar.
Tomas Pruzina

34

fopen vs C'de açık

1) bir sistem çağrısı iken fopenbir kütüphane fonksiyonuduropen .

2) fopensağlar tamponlu ES hızlı karşılaştırmak olan openhangi olmayan tampon .

3) fopenbir taşınabilir sırasında opendeğil taşınabilir ( açık bir ortam özgüdür ).

4) fopenbir DOSYA yapısına (DOSYA *) bir işaretçi döndürür ; opendosyayı tanımlayan bir tamsayı döndürür.

5) A FILE *size fscanf ve diğer stdio fonksiyonlarını kullanma yeteneği verir .


9
openbir POSIX standardı, bu yüzden oldukça taşınabilir
osvein

12

Kullanmanın opengerçek bir performans avantajı olduğu uygulamaların% 0,1'inin bir parçası olmadığınız sürece , gerçekten kullanmamanız için iyi bir neden yoktur fopen. Kadarıyla şöyle fdopensöz konusu dosya tanımlayıcıları ile oynarken değilse, o çağrıyı gerekmez.

İle sopa fopenve yöntemlerinin onun ailesi ( fwrite, fread, fprintf, ve diğerleri) ve çok memnun olacağım. En önemlisi, diğer programcılar kodunuzdan memnun kalacaklardır.


11

Eğer bir varsa FILE *, aşağıdaki gibi işlevleri kullanabilirsiniz fscanf, fprintfve fgetssadece dosya tanıtıcı varsa, giriş ve çıkış rutinleri sınırlı (ama muhtemelen daha hızlı) var vs read, writevs


7

Açık, okuma, yazma kullanmak, sinyal etkileşimleri hakkında endişelenmeniz gerektiği anlamına gelir.

Çağrı bir sinyal işleyici tarafından kesilirse, fonksiyonlar -1 döndürür ve errno değerini EINTR olarak ayarlar.

Yani bir dosyayı kapatmanın doğru yolu

while (retval = close(fd), retval == -1 && ernno == EINTR) ;

4
Çünkü closebu işletim sistemine bağlıdır. Döngüyü Linux, AIX ve diğer bazı işletim sistemlerinde yapmak yanlıştır.
Aralık'ta strcat

Buna ek olarak, okuma ve yazma kullanımı aynı sorunla karşılaşır, yani giriş / çıkışı tamamen işlemeden önce bir sinyal tarafından kesilebilirler ve programcı bu durumlarla başa çıkmak zorunda kalırken, fread ve fwrite sinyal kesintilerini güzelce ele alır.
Marcelo

6

open()bir sistem çağrısıdır ve Unix tabanlı sistemlere özgüdür ve bir dosya tanımlayıcı döndürür. write()Başka bir sistem çağrısı olan bir dosya tanımlayıcıya yazabilirsiniz .
fopen()bir dosya tanıtıcısı döndüren bir ANSI C işlev çağrısıdır ve diğer işletim sistemlerine taşınabilir. Kullanarak bir dosya tanıtıcısına yazabilirizfprintf .

Unix'te:
Dosya tanımlayıcısından aşağıdakileri kullanarak bir dosya işaretçisi alabilirsiniz:

fP = fdopen(fD, "a");

Aşağıdakileri kullanarak dosya tanıtıcısından bir dosya tanımlayıcı alabilirsiniz:

fD = fileno (fP);

4

fopen () ailesi işlevlerinin her birinin sonunda open () çağrılır . open () bir sistem çağrısıdır ve fopen () kütüphaneler tarafından kullanıcının kullanımı kolay bir sarmalayıcı işlevi olarak sağlanır


2

Uygulamam için fopen () 'den open () olarak değiştirdim, çünkü fopen fgetc'i her çalıştırdığımda fopen çift okumaya neden oluyordu. Çift okumalar, yapmaya çalıştığım şeyi rahatsız ediyordu. open () sadece istediğini yapıyor gibi görünüyor.


2

Hangi bayrakların açılması gerektiğine de bağlıdır. Yazma ve okuma (ve taşınabilirlik) kullanımıyla ilgili olarak yukarıda belirtildiği gibi f * kullanılmalıdır.

Ancak temel olarak standart bayraklardan (rw ve append bayrakları gibi) daha fazlasını belirtmek istiyorsanız, platforma özel bir API (POSIX açık gibi) veya bu ayrıntıları özetleyen bir kitaplık kullanmanız gerekir. C standardında böyle bayraklar yoktur.

Örneğin, bir dosyayı yalnızca dosyadan çıkarsa açmak isteyebilirsiniz. Oluşturma bayrağını belirtmezseniz dosyanın mevcut olması gerekir. Oluşturmak için özel eklerseniz, dosyayı yalnızca yoksa oluşturur. Daha çok var.

Örneğin Linux sistemlerinde sysfs aracılığıyla açıklanmış bir LED arayüzü vardır. Bir dosyanın içinden ledin parlaklığını ortaya çıkarır. 0-255 arasında bir sayı dizesi olarak yazma veya okuma. Elbette bu dosyayı oluşturmak ve sadece varsa yazmak istemezsiniz. Şimdi havalı şey: Standart çağrıları kullanarak bu dosyayı okumak / yazmak için fdopen kullanın.


0

diskteki bir dosyadan (dosyaya) bilgi okuyabilmemiz (veya yazabilmemiz için) önce fopen kullanarak bir dosyayı açarak dosyayı açmamız
gerekir. dosyayı açmak için fopen fonksiyonunu çağırdık.

1.firstly it searches on the disk the file to be opened.
2.then it loads the file from the disk into a place in memory called buffer.
3.it sets up a character pointer that points to the first character of the buffer.

bu fopen fonksiyonunun davranış şekli
tamponlama işlemi sırasında bazı nedenler vardır, zaman aşımı olabilir. bu nedenle fopen (yüksek seviye i / o) ile açık (düşük seviye i / o) sistem çağrısını karşılaştırırken, fopen'den daha hızlı daha uygundur .


daha hızlı açık mı?
obayhan

evet, open fopen'den daha hızlı olan sistem çağrısıdır - comparitively @obayhan
prashad
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.