C fopen เทียบกับเปิด


219

มีเหตุผลใดบ้าง (นอกเหนือจากวากยสัมพันธ์) ที่คุณต้องการใช้

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

หรือ

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

แทน

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

เมื่อใช้ C ในสภาพแวดล้อม Linux?


คุณหมายถึงfdopenและopenหรือfopenและopen?
user7116

คุณหมายถึง fopen ไม่ใช่ fdopen ใช่ไหม
Omnifarious

9
fopenเป็นส่วนหนึ่งของไลบรารี C มาตรฐานopenไม่ใช่ ใช้fopenเมื่อเขียนรหัสพกพา
Aziz

ใช่ฉันหมายถึง fopen ฉันเพิ่งอัปเดต แต่ฉันคิดว่าใช้หลักการเดียวกันนี้
LJM

6
@Aziz openเป็นฟังก์ชั่น POSIX แม้ว่า
dreamlax

คำตอบ:


243

ครั้งแรกไม่มีเหตุผลที่ดีโดยเฉพาะอย่างยิ่งที่จะใช้fdopenถ้าfopenเป็นตัวเลือกและopenเป็นตัวเลือกที่เป็นไปได้อื่น ๆ คุณไม่ควรจะใช้เพื่อเปิดไฟล์ในสถานที่แรกถ้าคุณต้องการopen FILE *ดังนั้นการรวมfdopenไว้ในรายการนั้นไม่ถูกต้องและทำให้สับสนเพราะมันไม่เหมือนกับคนอื่น ๆ ตอนนี้ฉันจะเพิกเฉยต่อความแตกต่างที่สำคัญเนื่องจากมาตรฐาน CFILE *และตัวอธิบายไฟล์เฉพาะระบบปฏิบัติการ

มีสี่เหตุผลหลักที่จะใช้แทนfopenopen

  1. fopen ช่วยให้คุณมีบัฟเฟอร์ IO ที่อาจเร็วกว่าสิ่งที่คุณทำ openที่จะเปิดออกมาเป็นจำนวนมากได้เร็วกว่าสิ่งที่คุณกำลังทำอยู่กับ
  2. fopen การแปลสิ้นสุดบรรทัดหากไฟล์ไม่ได้เปิดในโหมดไบนารีซึ่งจะมีประโยชน์มากหากโปรแกรมของคุณถูกย้ายไปยังสภาพแวดล้อมที่ไม่ใช่ Unix (แม้ว่าโลกจะปรากฏขึ้นเพื่อมาบรรจบกันบน LF-only (ยกเว้นเครือข่ายข้อความ IETF) โปรโตคอลเช่น SMTP และ HTTP และอื่น ๆ ))
  3. A FILE *ช่วยให้คุณสามารถใช้งานได้fscanfและฟังก์ชั่น stdio อื่น ๆ
  4. รหัสของคุณอาจต้องถูกย้ายไปยังแพลตฟอร์มอื่นที่รองรับ ANSI C เท่านั้นและไม่รองรับopenฟังก์ชั่นนี้

ในความคิดของฉันการแปลที่ลงท้ายด้วยบรรทัดมักจะเข้ามาช่วยคุณได้มากกว่าการแยกวิเคราะห์ fscanfนั้นอ่อนแอมากจนคุณต้องเลิกใช้มันเพื่อประโยชน์บางอย่างที่มีประโยชน์มากขึ้น

และแพลตฟอร์มส่วนใหญ่ที่รองรับ C มี openฟังก์ชั่น

นั่นเป็นคำถามที่ทิ้งไว้ ในสถานที่ที่คุณส่วนใหญ่อ่านหรือเขียนไฟล์ตามลำดับการสนับสนุนการกำหนดบัฟเฟอร์จะมีประโยชน์มากและมีการปรับปรุงความเร็วสูง แต่อาจนำไปสู่ปัญหาที่น่าสนใจซึ่งข้อมูลไม่ได้อยู่ในไฟล์เมื่อคุณคาดหวังว่ามันจะอยู่ที่นั่น คุณต้องจำไว้fcloseหรือfflushในเวลาที่เหมาะสม

หากคุณกำลังมองหา ( fsetposหรือfseekที่สองหรือที่สองคือเล่ห์เหลี่ยมเล็กน้อยที่จะใช้ในทางที่ได้มาตรฐาน) ประโยชน์ของการบัฟเฟอร์อย่างรวดเร็วลงไป

แน่นอนอคติของฉันคือฉันมักจะทำงานร่วมกับซ็อกเก็ตมากและมีความจริงที่ว่าคุณต้องการที่จะทำการปิดกั้น IO จริง ๆ (ซึ่งFILE *ล้มเหลวในการให้การสนับสนุนในทางที่สมเหตุสมผล) โดยไม่มีการบัฟเฟอร์เลย มีข้อกำหนดในการแยกวิเคราะห์ที่ซับซ้อนเพื่อให้สีของฉัน


4
ฉันจะไม่ถามประสบการณ์ของคุณ แต่ฉันชอบที่จะได้ยินคุณอธิบายรายละเอียดเล็กน้อยเกี่ยวกับเรื่องนี้ สำหรับแอพพลิเคชั่นประเภทใดที่คุณรู้สึกว่าการบัฟเฟอร์ในตัวเข้าทาง ปัญหาคืออะไรกันแน่?
Emil H

1
ไม่เห็นย่อหน้าสุดท้าย จุดที่ถูกต้อง IMHO เท่าที่ฉันสามารถบอกได้ว่าคำถามเกี่ยวกับไฟล์ IO แม้ว่า
Emil H

7
เพื่อชี้แจงเมื่อบัฟเฟอร์ได้รับในทาง มันเป็นเมื่อคุณใช้แสวงหา อ่านต่อไปนี้กับสิ่งที่คำสั่ง ( fgets, fgetc, fscanf, fread) มักจะอ่านทั้งขนาดของบัฟเฟอร์ (4K, 8K หรือสิ่งที่คุณตั้งไว้) ด้วยการใช้ direct I / O คุณสามารถหลีกเลี่ยงปัญหานั้นได้ ในกรณีนี้การใช้ดีกว่าpreadแทนคู่ค้นหา / อ่าน (1 syscall แทนที่จะเป็น 2)
Patrick Schlüter

2
การจัดการที่ถูกขัดจังหวะread()และการwrite()โทรเป็นเหตุผลข้อที่ห้าที่สะดวกในการใช้ฟังก์ชัน libc ตระกูล
nccc

3
@ m-ric: อืมนั่นเป็นคำถามที่ค่อนข้างไม่เกี่ยวข้อง แต่ใช่ แพลตฟอร์มทั้งหมดที่รองรับioctlการfilenoโทรที่รับFILE *และส่งกลับหมายเลขที่สามารถใช้ในการioctlโทรได้ ระวังให้ดี FILE *การเรียกที่เกี่ยวข้องอาจมีผลกระทบอย่างน่าประหลาดใจกับการใช้ioctlเพื่อเปลี่ยนแปลงบางอย่างเกี่ยวกับตัวอธิบายไฟล์ที่เกี่ยวข้อง
Omnifarious

53

open()เป็นการเรียกใช้ระบบปฏิบัติการระดับต่ำ fdopen()แปลง descriptor ไฟล์ระดับ os เป็น FILE-abstraction ระดับสูงกว่าของภาษา C fopen()โทรopen()ในพื้นหลังและให้ตัวชี้ไฟล์โดยตรง

มีข้อดีหลายประการในการใช้ FILE- วัตถุแทน file file descriptors ซึ่งรวมถึงความง่ายในการใช้งานมากขึ้น แต่ยังรวมถึงข้อดีทางเทคนิคอื่น ๆ เช่นการบัฟเฟอร์ในตัว โดยเฉพาะอย่างยิ่งการบัฟเฟอร์จะส่งผลให้เกิดข้อได้เปรียบด้านประสิทธิภาพเป็นอย่างมาก


3
มีข้อเสียใด ๆ ในการใช้เวอร์ชัน 'f ... ' แบบบัฟเฟอร์หรือไม่?
LJM

5
@L โมเซอร์ใช่เมื่อคุณบัฟเฟอร์ข้อมูลแล้วและด้วยเหตุนี้บัฟเฟอร์เพิ่มเติมเพิ่มการคัดลอกที่ไม่จำเป็นและค่าใช้จ่ายหน่วยความจำ
ไมเคิลแอรอน Safyan

6
จริงๆแล้วมีข้อเสียอื่น ๆ fopen()ไม่ได้ให้การควบคุมในระดับเดียวกันเมื่อเปิดไฟล์เช่นสร้างการอนุญาตโหมดการแชร์และอื่น ๆ โดยทั่วไปopen()และตัวแปรให้การควบคุมมากขึ้นใกล้เคียงกับสิ่งที่ระบบปฏิบัติการจริงให้
แมตต์ช่างไม้

2
นอกจากนี้ยังมีกรณีที่รุนแรงที่mmapไฟล์ของคุณและทำการเปลี่ยนแปลงด้วย I / O ปกติ (น่าเหลือเชื่ออย่างที่เราทำในโครงการของเราและด้วยเหตุผลที่ดีจริงๆ) การบัฟเฟอร์จะเป็นไปในทางที่
Patrick Schlüter

คุณอาจต้องการใช้ฟังก์ชั่นระบบอื่น ๆ เช่นการใช้ open () สำหรับการโหลดไฟล์ล่วงหน้าลงในแคชหน้าผ่าน readahead () ฉันคิดว่ากฎของหัวแม่มือคือ "ใช้ fopen เว้นแต่คุณจะต้องเปิดอย่างแน่นอน ()" เปิด () จริง ๆ แล้วช่วยให้คุณทำสิ่งแฟนซี (การตั้งค่า / ไม่ได้ตั้งค่า O_ATIME และคล้ายกัน)
Tomas Pruzina

34

fopen vs open ใน C

1) fopenเป็นฟังก์ชั่นห้องสมุดในขณะที่openเป็นการเรียกระบบสายระบบ

2) fopenให้บัฟเฟอร์ IOซึ่งจะเปรียบเทียบได้เร็วขึ้นopenซึ่งเป็นที่ไม่ใช่ Buffered

3) fopenเป็นแบบพกพาในขณะที่openไม่ได้พกพา ( เปิดเป็นสภาพแวดล้อมที่เฉพาะเจาะจง )

4) fopenส่งคืนตัวชี้ไปยังโครงสร้างไฟล์ (ไฟล์ *) ;openส่งคืนจำนวนเต็มที่ระบุไฟล์

5) A FILE *ให้ความสามารถในการใช้fscanfและฟังก์ชั่น stdio อื่น ๆ


9
openเป็นมาตรฐาน POSIX ดังนั้นมันจึงค่อนข้างพกพาได้
osvein

12

ถ้าคุณกำลังเป็นส่วนหนึ่งของ 0.1% ของการใช้งานที่ใช้เป็นประโยชน์การปฏิบัติจริงมีจริงๆไม่มีเหตุผลที่ดีที่จะไม่ใช้open fopenเท่าที่fdopenเป็นห่วงถ้าคุณไม่ได้เล่นกับอธิบายไฟล์ที่คุณไม่จำเป็นต้องโทร

Stick ที่มีfopenและครอบครัวของวิธีการ ( fwrite, fread, fprintf, et al) และคุณจะได้รับความพึงพอใจมาก โปรแกรมเมอร์สำคัญอื่น ๆ จะพึงพอใจกับรหัสของคุณ


11

หากคุณมีFILE *คุณสามารถใช้ฟังก์ชั่นเช่นfscanf, fprintfและfgetsอื่น ๆ หากคุณมีเพียงแค่อธิบายไฟล์ที่คุณมี จำกัด ( แต่น่าจะเร็วกว่า) input และ output กิจวัตรread, writeฯลฯ


7

การใช้เปิดอ่านเขียนหมายความว่าคุณต้องกังวลเกี่ยวกับสัญญาณรบกวน

หากการโทรถูกขัดจังหวะโดยตัวจัดการสัญญาณฟังก์ชั่นจะกลับ -1 และตั้งค่า errno เป็น EINTR

ดังนั้นวิธีที่เหมาะสมในการปิดไฟล์คือ

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

4
สำหรับcloseสิ่งนี้ขึ้นอยู่กับระบบปฏิบัติการ การวนซ้ำบน Linux, AIX และระบบปฏิบัติการอื่นไม่ถูกต้อง
strcat

นอกจากนี้การใช้การอ่านและการเขียนจะประสบปัญหาเดียวกันนั่นคือพวกมันสามารถถูกขัดจังหวะด้วยสัญญาณก่อนที่จะประมวลผลอินพุต / เอาต์พุตทั้งหมดและโปรแกรมเมอร์ต้องจัดการกับสถานการณ์เช่นนี้ในขณะที่ fread และ fwrite จัดการสัญญาณขัดจังหวะอย่างดี
Marcelo

6

open()เป็นการเรียกระบบและเฉพาะสำหรับระบบที่ใช้ Unix และส่งคืน file descriptor คุณสามารถเขียนถึง file descriptor โดยใช้write()ซึ่งเป็นการเรียกระบบอื่น
fopen()เป็นการเรียกใช้ฟังก์ชัน ANSI C ซึ่งส่งกลับตัวชี้ไฟล์และพกพาไปยังระบบปฏิบัติการอื่น ๆ ได้ เราสามารถเขียนตัวชี้ไฟล์โดยใช้fprintfเราสามารถเขียนถึงตัวชี้ไฟล์โดยใช้

ใน Unix:
คุณสามารถรับตัวชี้ไฟล์จาก file descriptor โดยใช้:

fP = fdopen(fD, "a");

คุณสามารถรับไฟล์ descriptor จากตัวชี้ไฟล์โดยใช้:

fD = fileno (fP);

4

open ()จะถูกเรียกในตอนท้ายของแต่ละฟังก์ชั่นของfopen () open ()เป็นการเรียกระบบและfopen ()ถูกจัดเตรียมโดยไลบรารีเป็นฟังก์ชัน wrapper สำหรับผู้ใช้ที่ใช้งานง่าย


2

ฉันเปลี่ยนเป็น open () จาก fopen () สำหรับแอปพลิเคชันของฉันเพราะ fopen ทำให้อ่านสองครั้งทุกครั้งที่ฉันวิ่ง fopen fgetc การอ่านซ้ำซ้อนทำให้เกิดสิ่งที่ฉันพยายามทำให้สำเร็จ open ดูเหมือนจะทำในสิ่งที่คุณขอ


2

ยังขึ้นอยู่กับว่าต้องเปิดแฟล็กใด ด้วยความเคารพต่อการใช้งานสำหรับการเขียนและการอ่าน (และการพกพา) f * ควรใช้ตามที่กล่าวไว้ข้างต้น

แต่ถ้าโดยทั่วไปต้องการระบุมากกว่าแฟล็กมาตรฐาน (เช่น rw และผนวกแฟล็ก) คุณจะต้องใช้ API เฉพาะแพลตฟอร์ม (เช่น POSIX เปิด) หรือไลบรารีที่สรุปรายละเอียดเหล่านี้ มาตรฐาน C ไม่มีแฟล็กดังกล่าว

ตัวอย่างเช่นคุณอาจต้องการเปิดไฟล์เฉพาะเมื่อไฟล์นั้นออก หากคุณไม่ได้ระบุการสร้างแฟล็กไฟล์จะต้องมีอยู่ หากคุณเพิ่มแบบเอกสิทธิ์เฉพาะบุคคลในการสร้างมันจะสร้างไฟล์เฉพาะหากไม่มีอยู่ ยังมีอีกมากมาย

ตัวอย่างเช่นบนระบบ Linux มีอินเตอร์เฟส LED เปิดเผยผ่าน sysfs มันเผยให้เห็นความสว่างของไฟ led ผ่านไฟล์ การเขียนหรืออ่านตัวเลขเป็นสตริงตั้งแต่ 0-255 แน่นอนคุณไม่ต้องการสร้างไฟล์นั้นและเขียนลงในไฟล์หากมีอยู่เท่านั้น สิ่งที่ยอดเยี่ยมตอนนี้: ใช้ fdopen เพื่ออ่าน / เขียนไฟล์นี้โดยใช้การโทรมาตรฐาน


0

การเปิดไฟล์โดยใช้fopen
ก่อนที่เราจะสามารถอ่าน (หรือเขียน) ข้อมูลจาก (ไป) ไฟล์บนดิสก์เราต้องเปิดไฟล์ เพื่อเปิดไฟล์ที่เราเรียกว่าฟังก์ชั่น 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.

วิธีการทำงานของฟังก์ชั่นfopen
มีสาเหตุบางอย่างในขณะที่กระบวนการบัฟเฟอร์มันอาจหมดเวลา ดังนั้นในขณะที่การเปรียบเทียบfopen (ระดับสูง I / O) ที่จะเปิด (ระดับต่ำ I / O) สายระบบและมันเป็นที่เหมาะสมได้เร็วขึ้นกว่าfopen


เปิดเร็วกว่า fopen ไหม
obayhan

ใช่openคือ system call ซึ่งเร็วกว่า fopen - comparitively @obayhan
prashad
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.