Czy jest jakiś powód (inny niż składniowy), z którego chciałbyś skorzystać
FILE *fdopen(int fd, const char *mode);
lub
FILE *fopen(const char *path, const char *mode);
zamiast
int open(const char *pathname, int flags, mode_t mode);
podczas używania C w środowisku Linux?
fdopen
iopen
lubfopen
iopen
?fopen
jest częścią standardowej biblioteki C,open
nie jest. Użyjfopen
podczas pisania przenośnego kodu.open
jest jednak funkcją POSIX.Odpowiedzi:
Po pierwsze, nie ma szczególnie dobrego powodu, aby użyć,
fdopen
jeślifopen
jest to opcja iopen
jest to drugi możliwy wybór. Nie powinieneś byłopen
otwierać pliku, jeśli chceszFILE *
. Dlatego umieszczeniefdopen
na tej liście jest niepoprawne i mylące, ponieważ nie jest bardzo podobne do innych. Teraz będę go ignorować, ponieważ ważne jest tutaj rozróżnienie między standardem C.FILE *
a deskryptorem pliku specyficznym dla systemu operacyjnego.Istnieją cztery główne powody, aby używać
fopen
zamiastopen
.fopen
zapewnia buforowanie operacji we / wy, które mogą okazać się znacznie szybsze niż to, co robiszopen
.fopen
wykonuje translację zakończeń linii, jeśli plik nie jest otwarty w trybie binarnym, co może być bardzo pomocne, jeśli Twój program jest kiedykolwiek przenoszony do środowiska innego niż Unix (chociaż świat wydaje się być zbieżny tylko w LF (z wyjątkiem sieci tekstowej IETF) protokoły takie jak SMTP i HTTP itp.).FILE *
daje możliwość korzystania zfscanf
innych funkcji stdio.open
funkcji.Moim zdaniem tłumaczenie kończące wiersz częściej
fscanf
przeszkadza, niż pomaga, a parsowanie jest tak słabe, że nieuchronnie kończy się to rzuceniem go na coś bardziej przydatnego.I większość platform obsługujących C ma
open
funkcję.To pozostawia pytanie buforujące. W miejscach, w których głównie czytasz lub zapisujesz plik sekwencyjnie, obsługa buforowania jest naprawdę pomocna i znacznie poprawia szybkość. Ale może to prowadzić do interesujących problemów, w których dane nie kończą się w pliku, gdy się go spodziewasz. Musisz pamiętać o tym
fclose
lubfflush
w odpowiednich momentach.Jeśli poszukujesz (aka
fsetpos
lubfseek
drugi jest nieco trudniejszy do użycia w sposób zgodny ze standardami), użyteczność buforowania szybko spada.Oczywiście, moja stronniczość polega na tym, że często pracuję z gniazdami, a tam jest fakt, że naprawdę chcesz robić nie blokujące IO (które
FILE *
całkowicie nie obsługuje w żaden rozsądny sposób) bez buforowania i często złożone wymagania dotyczące parsowania naprawdę koloryzują moje postrzeganie.źródło
fgets
,fgetc
,fscanf
,fread
), zawsze będzie przeczytać cały rozmiar bufora (4K, 8K lub cokolwiek ustawić). Korzystając z bezpośredniego wejścia / wyjścia możesz tego uniknąć. W takim przypadku lepiej jest użyćpread
zamiast pary wyszukiwania / odczytu (1 syscall zamiast 2).read()
iwrite()
wywołań jest wygodnym piątym powodem korzystania z rodziny funkcji libc.ioctl
takżefileno
połączenie, które przyjmujeFILE *
numer i zwraca numer, którego można użyć wioctl
połączeniu. Bądź jednak ostrożny.FILE *
wywołania pokrewne mogą zadziwiająco oddziaływać z użyciemioctl
do zmiany czegoś na temat podstawowego deskryptora pliku.open()
jest niskopoziomowym połączeniem OS.fdopen()
konwertuje deskryptor pliku na poziomie systemu operacyjnego na abstrakcyjną PLIK abstrakcję języka C.fopen()
wywołujeopen()
w tle i daje bezpośrednio wskaźnik PLIKU.Istnieje kilka korzyści z używania obiektów PLIK zamiast raczej surowych deskryptorów plików, co obejmuje większą łatwość użycia, ale także inne zalety techniczne, takie jak wbudowane buforowanie. Zwłaszcza buforowanie generalnie zapewnia znaczną przewagę wydajności.
źródło
fopen()
nie zapewnia tego samego poziomu kontroli podczas otwierania plików, na przykład tworzenia uprawnień, trybów udostępniania i innych. zazwyczajopen()
warianty zapewniają znacznie większą kontrolę, zbliżoną do tego, co faktycznie zapewnia system operacyjnymmap
plik i zmiany są wykonywane przy użyciu normalnego wejścia / wyjścia (choć wydaje się to niewiarygodne, faktycznie robimy to w naszym projekcie i to z naprawdę dobrych powodów), buforowanie byłoby przeszkodą.fopen vs open w C
1)
fopen
jest funkcją biblioteki, podczas gdyopen
jest wywołaniem systemowym .2)
fopen
zapewnia buforowane we / wy, które jest szybsze w porównaniu z tym,open
które nie jest buforowane .3)
fopen
jest przenośny, aleopen
nie przenośny ( otwarty jest specyficzny dla środowiska ).4)
fopen
zwraca wskaźnik do struktury PLIKU (PLIK *) ;open
zwraca liczbę całkowitą identyfikującą plik.5) A
FILE *
daje możliwość korzystania z fscanf i innych funkcji stdio.źródło
open
jest standardem POSIX, więc jest dość przenośnyO ile nie należysz do 0,1% aplikacji, w których używanie
open
to rzeczywista poprawa wydajności, naprawdę nie ma dobrego powodu, aby nie używaćfopen
. Jeśli chodzifdopen
o deskryptory plików, nie potrzebujesz tego połączenia.Stick with
fopen
a jego rodzina metod (fwrite
,fread
,fprintf
, et al) i będziesz bardzo zadowolony. Co równie ważne, inni programiści będą zadowoleni z twojego kodu.źródło
Jeśli masz
FILE *
, możesz korzystać z funkcji takich jakfscanf
,fprintf
ifgets
itd. Jeśli masz tylko deskryptor pliku, masz ograniczone (ale prawdopodobnie szybciej) procedury wejścia i wyjściaread
,write
etc.źródło
Korzystanie z otwartego, odczytu, zapisu oznacza, że musisz się martwić interceptami sygnałów.
Jeśli wywołanie zostało przerwane przez moduł obsługi sygnałów, funkcje zwrócą -1 i ustawią errno na EINTR.
Tak więc właściwym sposobem byłoby zamknięcie pliku
źródło
close
to zależy od systemu operacyjnego. Pętla nie jest wykonywana w systemie Linux, AIX i niektórych innych systemach operacyjnych.open()
to wywołanie systemowe specyficzne dla systemów opartych na Uniksie i zwraca deskryptor pliku. Możesz pisać do deskryptora pliku, używającwrite()
innego wywołania systemowego.fopen()
to wywołanie funkcji ANSI C, które zwraca wskaźnik pliku i jest przenośne na inne systemy operacyjne. Możemy pisać do wskaźnika pliku za pomocąfprintf
.W
systemie Unix: wskaźnik pliku można uzyskać z deskryptora pliku, używając:
Deskryptor pliku można uzyskać ze wskaźnika pliku, używając:
źródło
open () zostanie wywołany na końcu każdej funkcji rodziny fopen () . open () to wywołanie systemowe, a biblioteki fopen () są dostarczane przez biblioteki jako funkcje otoki dla łatwego użycia przez użytkownika
źródło
Zmieniłem na open () z fopen () dla mojej aplikacji, ponieważ fopen powodował podwójne odczyty przy każdym uruchomieniu fopen fgetc. Podwójne odczyty zakłócały to, co próbowałem osiągnąć. wydaje się, że open () robi to, o co go prosisz.
źródło
Zależy również od tego, jakie flagi są wymagane do otwarcia. W odniesieniu do użycia do pisania i czytania (i przenośności) należy użyć f *, jak argumentowano powyżej.
Ale jeśli w zasadzie chcesz podać więcej niż standardowe flagi (takie jak flagi rw i append), będziesz musiał użyć interfejsu API specyficznego dla platformy (jak POSIX open) lub biblioteki, która wyodrębnia te szczegóły. Standard C nie ma takich flag.
Na przykład możesz chcieć otworzyć plik, tylko jeśli zostanie zamknięty. Jeśli nie określisz flagi tworzenia, plik musi istnieć. Jeśli dodasz wyłączność do utworzenia, plik zostanie utworzony tylko wtedy, gdy nie istnieje. Jest o wiele więcej.
Na przykład w systemach Linux dostępny jest interfejs LED odsłonięty przez sysfs. Odsłania jasność diody LED przez plik. Zapis lub odczyt liczby w postaci ciągu od 0-255. Oczywiście nie chcesz tworzyć tego pliku i pisać do niego tylko wtedy, gdy on istnieje. Fajna rzecz: użyj fdopen do odczytu / zapisu tego pliku za pomocą standardowych wywołań.
źródło
otwierając plik za pomocą fopen,
zanim będziemy mogli odczytać (lub zapisać) informacje z (do) pliku na dysku, musimy go otworzyć. aby otworzyć plik, wywołaliśmy funkcję fopen.
ten sposób zachowania funkcji fopen
ma pewne przyczyny podczas buforowania, może upłynąć limit czasu. więc porównując fopen (wysoki poziom we / wy) z otwartym wywołaniem systemowym (niski poziom we / wy), i jest to szybsze bardziej odpowiednie niż fopen .
źródło