C fopen vs terbuka

219

Apakah ada alasan (selain yang sintaksis) yang ingin Anda gunakan

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

atau

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

dari pada

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

saat menggunakan C di lingkungan Linux?

LJM
sumber
Apakah maksud Anda fdopendan openatau fopendan open?
user7116
Bukankah maksud Anda fopen, bukan fdopen?
Mahakuasa
9
fopenadalah bagian dari pustaka C standar, openbukan. Gunakan fopensaat menulis kode portabel.
Aziz
Ya, maksudku fopen. Saya baru saja memperbaruinya, tetapi saya pikir prinsip yang sama berlaku.
LJM
6
@ Aziz, openadalah fungsi POSIX.
dreamlax

Jawaban:

242

Pertama, tidak ada alasan yang sangat baik untuk digunakan fdopenjika fopenmerupakan opsi dan openmerupakan pilihan lain yang memungkinkan. Anda seharusnya tidak terbiasa openmembuka file di tempat pertama jika Anda menginginkan FILE *. Jadi termasuk fdopendalam daftar itu tidak benar dan membingungkan karena tidak banyak seperti yang lain. Saya sekarang akan melanjutkan untuk mengabaikannya karena perbedaan penting di sini adalah antara standar C FILE *dan deskriptor file khusus-OS.

Ada empat alasan utama untuk menggunakan fopenbukan open.

  1. fopenmemberi Anda IO buffering yang ternyata jauh lebih cepat dari apa yang Anda lakukan open.
  2. fopen tidak terjemahan akhir baris jika file tidak dibuka dalam mode biner, yang dapat sangat membantu jika program Anda pernah porting ke lingkungan non-Unix (meskipun dunia tampaknya konvergen pada LF-only (kecuali jaringan berbasis teks IETF protokol seperti SMTP dan HTTP dan semacamnya)).
  3. A FILE *memberi Anda kemampuan untuk menggunakan fscanfdan fungsi stdio lainnya.
  4. Kode Anda suatu hari nanti mungkin perlu porting ke beberapa platform lain yang hanya mendukung ANSI C dan tidak mendukung openfungsinya.

Menurut pendapat saya, terjemahan akhir baris lebih sering menghalangi Anda daripada membantu Anda, dan penguraiannya fscanfsangat lemah sehingga Anda akhirnya terpaksa membuangnya demi sesuatu yang lebih berguna.

Dan sebagian besar platform yang mendukung C memiliki openfungsi.

Itu meninggalkan pertanyaan buffering. Di tempat-tempat di mana Anda membaca atau menulis file secara berurutan, dukungan buffer sangat membantu dan peningkatan kecepatan yang besar. Tapi itu bisa menyebabkan beberapa masalah menarik di mana data tidak berakhir di file ketika Anda mengharapkannya ada di sana. Anda harus mengingat fcloseatau fflushpada waktu yang tepat.

Jika Anda melakukan pencarian (alias fsetposatau fseekyang sedikit lebih sulit untuk digunakan dengan cara yang sesuai standar), kegunaan buffering dengan cepat turun.

Tentu saja, bias saya adalah bahwa saya cenderung bekerja dengan soket banyak, dan ada fakta bahwa Anda benar-benar ingin melakukan IO non-blocking (yang FILE *benar-benar gagal mendukung dengan cara yang masuk akal) tanpa buffering sama sekali dan sering memiliki persyaratan parsing yang kompleks benar-benar mewarnai persepsi saya.

Beraneka ragam
sumber
4
Saya tidak akan mempertanyakan pengalaman Anda, tetapi saya ingin mendengar Anda sedikit menjelaskan hal ini. Untuk jenis aplikasi apa Anda merasa bahwa buffering bawaan menghalangi? Apa sebenarnya masalahnya?
Emil H
1
Tidak melihat paragraf terakhir. Poin yang valid, IMHO. Sejauh yang saya tahu pertanyaannya adalah tentang file IO.
Emil H
7
Untuk mengklarifikasi ketika buffering menghalangi. Itu saat Anda menggunakan mencari. Berikut membaca dengan perintah apapun ( fgets, fgetc, fscanf, fread), akan selalu membaca seluruh ukuran buffer (4K, 8K atau apa pun yang Anda tetapkan). Dengan menggunakan I / O langsung, Anda dapat menghindarinya. Dalam hal ini lebih baik menggunakan preaddaripada mencari / membaca pasangan (1 syscall, bukan 2).
Patrick Schlüter
2
Menangani panggilan terputus read()dan write()merupakan alasan kelima yang nyaman untuk menggunakan keluarga fungsi libc.
nccc
3
@ m-ric: Ya, itu pertanyaan yang agak tidak berhubungan, tapi ya. Semua platform yang mendukung ioctljuga mendukung filenopanggilan yang mengambil FILE *dan mengembalikan nomor yang dapat digunakan dalam ioctlpanggilan. Berhati-hatilah. FILE *panggilan terkait dapat berinteraksi secara mengejutkan dengan menggunakan ioctluntuk mengubah sesuatu tentang deskriptor file yang mendasarinya.
Mahakuasa
53

open()adalah panggilan os tingkat rendah. fdopen()mengkonversi deskriptor file os-level ke abstraksi FILE tingkat tinggi dari bahasa C. fopen()panggilan open()di latar belakang dan memberi Anda FILE-pointer secara langsung.

Ada beberapa keuntungan menggunakan FILE-objek, bukan deskriptor file mentah, yang mencakup kemudahan penggunaan yang lebih besar tetapi juga keuntungan teknis lainnya seperti buffering bawaan. Terutama buffering umumnya menghasilkan keuntungan kinerja yang cukup besar.

Emil H
sumber
3
Apakah ada kerugian menggunakan versi 'f ...' buffered terbuka?
LJM
5
@L. Moser, ya, ketika Anda sudah membuat buffer data, dan karenanya buffer tambahan menambahkan penyalinan dan memori yang tidak perlu.
Michael Aaron Safyan
6
sebenarnya ada kerugian lainnya. fopen()tidak memberikan tingkat kontrol yang sama saat membuka file, misalnya membuat izin, mode berbagi, dan banyak lagi. biasanya open()dan varian memberikan lebih banyak kontrol, dekat dengan apa sistem operasi benar-benar menyediakan
Matt Joiner
2
Ada juga kasus ekstrem di mana Anda mmapfile dan melakukan perubahan dengan I / O normal (luar biasa seperti kedengarannya kita lakukan sebenarnya dalam proyek kami dan untuk alasan yang sangat baik), buffering akan menghalangi.
Patrick Schlüter
Anda juga mungkin ingin menggunakan fungsi sistem lain, seperti menggunakan open () untuk preloading file ke cache halaman melalui readahead (). Saya kira aturannya adalah "gunakan fopen kecuali Anda benar-benar perlu open ()", open () sebenarnya memungkinkan Anda melakukan hal-hal mewah (pengaturan / bukan pengaturan O_ATIME dan sejenisnya).
Tomas Pruzina
34

fopen vs terbuka di C

1) fopenadalah fungsi perpustakaan sementara openadalah panggilan sistem .

2) fopenmenyediakan IO buffered yang lebih cepat dibandingkan openyang non buffered .

3) fopenadalah portable sementara opentidak portabel ( terbuka adalah spesifik lingkungan ).

4) fopenmengembalikan pointer ke struktur FILE (FILE *) ; openmengembalikan bilangan bulat yang mengidentifikasi file.

5) A FILE *memberi Anda kemampuan untuk menggunakan fscanf dan fungsi stdio lainnya.

Yogeesh HT
sumber
9
openadalah standar POSIX, jadi ini cukup portabel
osvein
12

Kecuali Anda bagian dari 0,1% aplikasi yang menggunakan openmanfaat kinerja sebenarnya, tidak ada alasan kuat untuk tidak menggunakannya fopen. Sejauh fdopenmenyangkut, jika Anda tidak bermain dengan deskriptor file, Anda tidak perlu panggilan itu.

Tongkat dengan fopendan keluarganya metode ( fwrite, fread, fprintf, et al) dan Anda akan sangat puas. Sama pentingnya, programmer lain akan puas dengan kode Anda.

pengguna7116
sumber
11

Jika Anda memiliki FILE *, Anda dapat menggunakan fungsi seperti fscanf, fprintfdan fgetslain - lain. Jika Anda baru saja mendeskripsikan file, Anda telah membatasi (tetapi kemungkinan lebih cepat) rutinitas input dan output read, writedll.

dreamlax
sumber
7

Menggunakan open, read, write berarti Anda harus khawatir tentang interaksi sinyal.

Jika panggilan terputus oleh pengendali sinyal, fungsi akan mengembalikan -1 dan mengatur errno ke EINTR.

Jadi cara yang tepat untuk menutup file adalah

while (retval = close(fd), retval == -1 && ernno == EINTR) ;
Digy
sumber
4
Sebab close, ini tergantung pada sistem operasi. Tidak benar untuk melakukan loop pada Linux, AIX dan beberapa sistem operasi lainnya.
strcat
Selain itu, menggunakan baca dan tulis akan mengalami masalah yang sama, yaitu, mereka dapat terganggu oleh sinyal sebelum memproses input / output sepenuhnya dan programmer harus menangani situasi seperti itu, sementara fread dan fwrite menangani gangguan sinyal dengan baik.
Marcelo
6

open()adalah panggilan sistem dan khusus untuk sistem berbasis Unix dan mengembalikan deskriptor file. Anda dapat menulis ke deskriptor file menggunakan write()yang merupakan panggilan sistem lain.
fopen()adalah panggilan fungsi ANSI C yang mengembalikan penunjuk file dan portabel untuk OS lainnya. Kita bisa menulis ke penunjuk file menggunakan fprintf.

Di Unix:
Anda bisa mendapatkan pointer file dari deskriptor file menggunakan:

fP = fdopen(fD, "a");

Anda bisa mendapatkan deskriptor file dari penunjuk file menggunakan:

fD = fileno (fP);
Arun Chettoor
sumber
4

open () akan dipanggil di akhir setiap fungsi keluarga fopen () . open () adalah panggilan sistem dan fopen () disediakan oleh perpustakaan sebagai fungsi pembungkus agar pengguna mudah digunakan

theadnangondal
sumber
2

Saya berubah menjadi open () dari fopen () untuk aplikasi saya, karena fopen menyebabkan pembacaan ganda setiap kali saya menjalankan fopen fgetc. Bacaan ganda mengganggu apa yang saya coba capai. open () sepertinya melakukan apa yang Anda minta.

Ersatz Splatt
sumber
2

Tergantung juga pada bendera apa yang harus dibuka. Sehubungan dengan penggunaan untuk menulis dan membaca (dan portabilitas) f * harus digunakan, sebagaimana didalilkan di atas.

Tetapi jika pada dasarnya ingin menentukan lebih dari flag standar (seperti bendera rw dan append), Anda harus menggunakan API khusus platform (seperti POSIX terbuka) atau perpustakaan yang mengabstraksi detail ini. Standar-C tidak memiliki flag semacam itu.

Misalnya Anda mungkin ingin membuka file, hanya jika itu keluar. Jika Anda tidak menentukan flag buat, file tersebut harus ada. Jika Anda menambahkan eksklusif untuk dibuat, itu hanya akan membuat file jika tidak ada. Masih banyak lagi.

Sebagai contoh pada sistem Linux ada antarmuka LED yang diekspos melalui sysfs. Itu memperlihatkan kecerahan led melalui file. Menulis atau membaca angka sebagai string mulai dari 0-255. Tentu saja Anda tidak ingin membuat file itu dan hanya menulis kepadanya jika ada. Yang keren sekarang: Gunakan fdopen untuk membaca / menulis file ini menggunakan panggilan standar.

Ritualmaster
sumber
0

membuka file menggunakan fopen
sebelum kita dapat membaca (atau menulis) informasi dari (ke) file pada disk kita harus membuka file. untuk membuka file, kami telah memanggil fungsi fopen.

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.

ini cara perilaku fungsi fopen
ada beberapa penyebab saat proses buffering, mungkin waktu habis. jadi sambil membandingkan fopen (tingkat tinggi i / o) untuk membuka (tingkat rendah i / o) panggilan sistem, dan itu lebih cepat lebih tepat daripada fopen .

prashad
sumber
terbuka lebih cepat dari fopen?
obayhan
ya, terbuka adalah panggilan sistem, yang lebih cepat daripada fopen - komparatif @obayhan
prashad