ฉันต้องการทราบความแตกต่างระหว่างตัวอธิบายไฟล์และตัวชี้ไฟล์
นอกจากนี้คุณจะใช้สถานการณ์ใดแทนอีกสถานการณ์หนึ่ง
ฉันต้องการทราบความแตกต่างระหว่างตัวอธิบายไฟล์และตัวชี้ไฟล์
นอกจากนี้คุณจะใช้สถานการณ์ใดแทนอีกสถานการณ์หนึ่ง
คำตอบ:
File descriptor คือ "หมายเลขอ้างอิง" จำนวนเต็มระดับต่ำที่ใช้เพื่อระบุไฟล์ที่เปิด (หรือซ็อกเก็ตหรืออะไรก็ตาม) ที่ระดับเคอร์เนลใน Linux และระบบอื่น ๆ ที่คล้าย Unix
คุณผ่าน "เปล่า" อธิบายไฟล์โทรยูนิกซ์ที่เกิดขึ้นจริงเช่นread()
, write()
และอื่น ๆ
FILE
ชี้เป็นสร้างห้องสมุดระดับมาตรฐาน C, ใช้ในการแสดงไฟล์ FILE
wraps อธิบายไฟล์และเพิ่มบัฟเฟอร์และคุณสมบัติอื่น ๆ ที่จะทำให้ I / O ได้ง่ายขึ้น
คุณผ่านFILE
ตัวชี้ไปยังฟังก์ชัน C มาตรฐานเช่นและfread()
fwrite()
fd
เป็นอาร์กิวเมนต์แรกread()
ของ ทำไมเรียกว่าเปล่า?
FILE *
ประเภทของไลบรารีมาตรฐานตัวอธิบายไฟล์จำนวนเต็มจะ "ห่อน้อยกว่า" นั่นคือ "เปล่า"
หนึ่งถูกบัฟเฟอร์ ( FILE *
) และอีกอันไม่ใช่ ในทางปฏิบัติคุณต้องการใช้FILE *
เกือบตลอดเวลาเมื่อคุณอ่านจากไฟล์ 'จริง' (เช่นในไดรฟ์) เว้นแต่คุณจะรู้ว่าคุณกำลังทำอะไรอยู่หรือเว้นแต่ว่าไฟล์ของคุณเป็นซ็อกเก็ตจริง ๆ ..
คุณสามารถรับ file descriptor จากการFILE *
ใช้งานfileno()
และคุณสามารถเปิดบัฟเฟอร์FILE *
จาก file descriptor โดยใช้ไฟล์fdopen()
ตัวอธิบายไฟล์เป็นเพียงจำนวนเต็มที่คุณได้รับจากการopen()
เรียกPOSIX การใช้มาตรฐาน C fopen()
คุณจะได้โครงสร้างFILE
กลับคืนมา โครงสร้างFILE
ประกอบด้วยตัวอธิบายไฟล์นี้ท่ามกลางสิ่งอื่น ๆ เช่นจุดสิ้นสุดของไฟล์และตัวบ่งชี้ข้อผิดพลาดตำแหน่งสตรีมเป็นต้น
ดังนั้นการใช้จะช่วยให้คุณมีจำนวนหนึ่งของนามธรรมเมื่อเทียบกับfopen()
open()
โดยทั่วไปคุณควรใช้fopen()
เนื่องจากเป็นแบบพกพามากกว่าและคุณสามารถใช้ฟังก์ชัน C มาตรฐานอื่น ๆ ทั้งหมดที่ใช้โครงสร้างFILE
เช่นfprintf()
และตระกูลได้
ไม่มีปัญหาด้านประสิทธิภาพการใช้งานอย่างใดอย่างหนึ่ง
ตัวอธิบายไฟล์เทียบกับตัวชี้ไฟล์
ตัวอธิบายไฟล์:
File Descriptor คือค่าจำนวนเต็มที่ส่งคืนโดยการopen()
เรียกระบบ
int fd = open (filePath, mode);
ตัวชี้ไฟล์:
ตัวชี้ไฟล์เป็นตัวชี้ไปยังโครงสร้าง C ที่ส่งคืนโดยfopen()
ฟังก์ชันไลบรารีซึ่งใช้ในการระบุไฟล์การตัดคำอธิบายไฟล์ฟังก์ชันการบัฟเฟอร์และฟังก์ชันอื่น ๆ ทั้งหมดที่จำเป็นสำหรับการดำเนินการ I / Oตัวชี้ไฟล์เป็นประเภทFILEซึ่งมีคำจำกัดความ สามารถพบได้ใน"/usr/include/stdio.h" คำจำกัดความนี้อาจแตกต่างกันไปในแต่ละคอมไพเลอร์
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;
ต้องการเพิ่มคะแนนที่อาจเป็นประโยชน์
เกี่ยวกับ FILE *
ฉันใช้มันหลายครั้งสำหรับบันทึกการแก้ไขข้อบกพร่อง ตัวอย่าง,
FILE *fp;
fp = fopen("debug.txt","a");
fprintf(fp,"I have reached till this point");
fclose(fp);
เกี่ยวกับ FILE DESCRIPTOR
โดยทั่วไปจะใช้สำหรับ IPC
ให้การควบคุมระดับต่ำแก่ไฟล์ในระบบ * nix (อุปกรณ์ไฟล์ซ็อกเก็ต ฯลฯ ) จึงมีประสิทธิภาพมากกว่าไฟล์FILE *
.
fdopen()
ทำสิ่งต่างๆเช่น IPC และอุปกรณ์ด้วยFILE*
ไม่ได้หรือ?
FILE*
แต่คุณสามารถสร้างFILE*
จาก file descriptor ( fdopen()
) และในภายหลังการปิดFILE
จะเป็นการปิด descriptor ด้วย ดังนั้นคุณสามารถทำ IPC ได้ แต่คุณต้องจัดการกับตัวอธิบายไฟล์เล็กน้อยเพื่ออำนวยความสะดวกให้กับ IPC โดยตรง
FILE *
เป็นประโยชน์มากขึ้นเมื่อคุณทำงานกับไฟล์ข้อความและท่านผู้ใช้ / ส่งออกเพราะมันช่วยให้คุณใช้ฟังก์ชัน API เช่นsprintf()
, sscanf()
, fgets()
, feof()
ฯลฯ
File descriptor API อยู่ในระดับต่ำดังนั้นจึงอนุญาตให้ทำงานกับซ็อกเก็ตไปป์ไฟล์ที่แมปหน่วยความจำ (และแน่นอนว่าไฟล์ทั่วไป)
เพียงแค่ทราบเพื่อจบการอภิปราย (หากสนใจ) ....
fopen
อาจไม่ปลอดภัยและคุณควรใช้fopen_s
หรือopen
ตั้งค่าบิตพิเศษ C1X ที่จะนำเสนอx
รูปแบบเพื่อให้คุณสามารถfopen
ด้วยโหมด"rx"
, "wx"
ฯลฯ
ถ้าคุณใช้open
คุณอาจพิจารณาหรือopen(..., O_EXCL | O_RDONLY,... )
open(..., O_CREAT | O_EXCL | O_WRONLY,... )
ดูตัวอย่างเช่นอย่าทำให้สมมติฐานเกี่ยวกับ fopen () และการสร้างแฟ้ม
fopen_s
ดูเหมือนจะไม่สามารถใช้ได้กับPOSIX
ผมถือว่า soultion พกพามากที่สุดก็จะไปแล้วopen(2)
fdopen(2)
(ทิ้งหน้าต่างไว้ข้างๆ) นอกจากนี้อะไรจะเร็วขึ้นfopen_s()
หรือopen(2)
ตามด้วยfdopen(2)
?
การเรียกระบบส่วนใหญ่ใช้ file descriptor เช่นread
และ write
. ฟังก์ชันไลบรารีจะใช้ตัวชี้ไฟล์ ( printf
, scanf
) แต่ฟังก์ชันของไลบรารีใช้การเรียกระบบภายในเท่านั้น
ฉันพบแหล่งข้อมูลที่ดีที่นี่โดยให้ภาพรวมระดับสูงของความแตกต่างระหว่างสองสิ่งนี้:
เมื่อคุณต้องการป้อนข้อมูลหรือเอาต์พุตไปยังไฟล์คุณมีทางเลือกของกลไกพื้นฐานสองอย่างสำหรับแสดงการเชื่อมต่อระหว่างโปรแกรมของคุณและไฟล์: file descriptors และ stream ตัวอธิบายไฟล์แสดงเป็นอ็อบเจ็กต์ประเภท int ในขณะที่สตรีมแสดงเป็นอ็อบเจ็กต์ FILE *
File descriptors จัดเตรียมอินเทอร์เฟซระดับต่ำแบบดั้งเดิมสำหรับการดำเนินการอินพุตและเอาต์พุต ทั้งตัวอธิบายไฟล์และสตรีมสามารถแสดงถึงการเชื่อมต่อกับอุปกรณ์ (เช่นเทอร์มินัล) หรือไปป์หรือซ็อกเก็ตสำหรับการสื่อสารกับกระบวนการอื่นเช่นเดียวกับไฟล์ปกติ แต่ถ้าคุณต้องการควบคุมการดำเนินการที่เฉพาะเจาะจงสำหรับอุปกรณ์บางประเภทคุณต้องใช้ตัวอธิบายไฟล์ ไม่มีสิ่งอำนวยความสะดวกในการใช้สตรีมด้วยวิธีนี้ คุณต้องใช้ตัวอธิบายไฟล์ด้วยหากโปรแกรมของคุณจำเป็นต้องทำการอินพุตหรือเอาต์พุตในโหมดพิเศษเช่นอินพุตแบบไม่บล็อก (หรือโพล) (ดูสถานะไฟล์สถานะ)
สตรีมจัดเตรียมอินเทอร์เฟซระดับสูงขึ้นโดยจัดชั้นไว้ด้านบนของสิ่งอำนวยความสะดวกตัวอธิบายไฟล์ดั้งเดิม อินเทอร์เฟซสตรีมถือว่าไฟล์ทุกประเภทเหมือนกันมากยกเว้นเพียงอย่างเดียวคือรูปแบบการบัฟเฟอร์สามรูปแบบที่คุณสามารถเลือกได้ (ดู Stream Buffering)
ข้อได้เปรียบหลักของการใช้อินเทอร์เฟซสตรีมคือชุดของฟังก์ชันสำหรับการดำเนินการอินพุตและเอาต์พุตจริง (ซึ่งตรงข้ามกับการดำเนินการควบคุม) บนสตรีมนั้นสมบูรณ์กว่าและมีประสิทธิภาพมากกว่าสิ่งอำนวยความสะดวกที่เกี่ยวข้องสำหรับตัวอธิบายไฟล์ อินเทอร์เฟซตัวอธิบายไฟล์มีฟังก์ชันง่ายๆสำหรับการถ่ายโอนบล็อกของอักขระเท่านั้น แต่อินเทอร์เฟซสตรีมยังมีฟังก์ชันอินพุตและเอาต์พุตที่มีรูปแบบที่มีประสิทธิภาพ (printf และ scanf) รวมทั้งฟังก์ชันสำหรับอินพุตและเอาต์พุตที่เน้นอักขระและบรรทัด
เนื่องจากสตรีมถูกนำไปใช้ในแง่ของ file descriptor คุณสามารถแยก file descriptor จากสตรีมและดำเนินการระดับต่ำได้โดยตรงบน file descriptor คุณยังสามารถเปิดการเชื่อมต่อเป็นตัวอธิบายไฟล์จากนั้นสร้างสตรีมที่เชื่อมโยงกับตัวอธิบายไฟล์นั้น
โดยทั่วไปคุณควรใช้สตรีมมากกว่าตัวอธิบายไฟล์เว้นแต่จะมีการดำเนินการบางอย่างที่คุณต้องการทำซึ่งสามารถทำได้เฉพาะกับตัวอธิบายไฟล์เท่านั้น หากคุณเป็นโปรแกรมเมอร์เริ่มต้นและไม่แน่ใจว่าจะใช้ฟังก์ชันใดเราขอแนะนำให้คุณมุ่งเน้นไปที่ฟังก์ชันอินพุตที่จัดรูปแบบ (ดูอินพุตที่จัดรูปแบบ) และฟังก์ชันเอาต์พุตที่จัดรูปแบบ (ดูเอาต์พุตที่จัดรูปแบบ)
หากคุณกังวลเกี่ยวกับความสามารถในการพกพาโปรแกรมของคุณไปยังระบบอื่นที่ไม่ใช่ GNU คุณควรทราบด้วยว่าตัวอธิบายไฟล์ไม่สามารถพกพาได้เหมือนกับสตรีม คุณสามารถคาดหวังว่าระบบใด ๆ ที่รัน ISO C เพื่อรองรับสตรีม แต่ระบบที่ไม่ใช่ GNU อาจไม่สนับสนุนตัวอธิบายไฟล์เลยหรืออาจใช้เฉพาะส่วนย่อยของฟังก์ชัน GNU ที่ทำงานกับตัวอธิบายไฟล์ อย่างไรก็ตามฟังก์ชันตัวอธิบายไฟล์ส่วนใหญ่ในไลบรารี GNU C รวมอยู่ในมาตรฐาน POSIX.1