هل هناك أي سبب عادي لاستخدام Open () بدلا من FOPEN ()؟
سؤال
أقوم بمشروع صغير في ج بعد فترة طويلة بعيدا عن ذلك. تحدث هذه لتضمين بعض معالجة الملفات. لقد لاحظت في وثائق مختلفة أن هناك وظائف تعود FILE *
مقابض وغيرها من أي ظهور (عدد صحيح صغير). تقدم كلتا المجموعتين من الوظائف نفس الخدمات الأساسية التي أحتاج إليها، لذلك لا يهم حقا استخدامها.
لكنني فضولي حول حكمة المجموعة: هل من الأفضل استخدامها fopen()
والأصدقاء، أو open()
والأصدقاء؟
يحرر نظرا لأن شخصا ما ذكر مؤشرا مؤقتا مقابل الأجهزة والوصول إليها، أود أن أضيف أن جزءا من هذا المشروع الصغير سيكون كتابة برنامج تشغيل نظام ملفات للمستخدمين ضمن الصمامات. لذلك يمكن الوصول إلى مستوى الملف بسهولة على جهاز (على سبيل المثال CDROM أو محرك الأقراص SCSI) كما في "ملف" (أي صورة).
المحلول
الاعتراض الذي "FOPEN" محمول و "فتح" ليس هو وهمية.
FOPEN جزء من LIBC، فتح مكالمة نظام Posix.
كلها محمولة مثل المكان الذي يأتون منه.
I / O إلى ملفات fopen'ed هو (يجب أن تفترض أنه قد يكون، والأغراض العملية، هو) مخزنة من قبل libc، واصطفات الملفات المفتوحة () ED ليست مخزنة من قبل libc (قد تكون كذلك، وعادة ما تكون عادة مخزنة في نظام الملفات - ولكن ليس كل ما تفتحه () هو ملف على نظام ملفات.
ما هي نقطة fopen'ing، على سبيل المثال، عقدة جهاز مثل / dev / sg0، أو / dev / tty0 ... ماذا ستفعل؟ أنت ستفعل Ioctl على ملف *؟ حظا جيدا في ذلك.
ربما تريد فتح بعض الأعلام مثل O_Direct - لا معنى له مع FOPEN ().
نصائح أخرى
من الأفضل استخدام Open () إذا كنت تلتصقا لأنظمة مثل UNIX وقد ترغب في:
- لديك المزيد من التحكم في الحبيبات الجميلة على أجزاء إذن UNIX على إنشاء الملفات.
- استخدم الوظائف ذات المستوى الأدنى مثل القراءة / الكتابة / mmap بدلا من وظائف دفق I / O المخزونة C.
- استخدم جدولة IO واصف الملفات (FD) المستندات (الاستطلاع، حدد، وما إلى ذلك)، يمكنك بالطبع الحصول على FD من ملف * باستخدام Fileno ()، ولكن يجب أن تؤخذ الرعاية لعدم مزج الملفات القائمة على الوظائف القائمة على الوظائف المستندة إلى FD وبعد
- افتح أي جهاز خاص (وليس ملف منتظم)
من الأفضل استخدام FOPEN / FRWWRITE / FWWRITE للحصول على أقصى قدر من إمكانية النقل، لأن هذه هي وظائف C القياسية، والوظائف التي ذكرتها أعلاه ليست كذلك.
يعمل FOPEN على مستوى أعلى من Open .... FOPEN يعيدك مؤشر إلى تيار الملفات مما يشبه تجريد الدفق الذي تقرأه في C ++
افتح إرجاع لك واصف الملفات لفتح الملف ... إنه لا يوفر عليك تجريد دفق وأنت مسؤول عن التعامل مع البتات والايت بايت ... هذا على مستوى أقل بالمقارنة مع FOPEN
تيارات Stdio مخزنة مؤقتا، في حين أن ملفات الملفات المفتوحة () ليست كذلك. يعتمد على ما تحتاجه. يمكنك أيضا إنشاء واحد من الآخر:
إرجاع Int Fileno (File * Stream) واصف الملف للحصول على ملف *، ملف * FDOPEN (Int Fildes، Const Char * Mode) إنشاء ملف * من واصف الملفات.
توخي الحذر عند التعامل مع INTMIXING مؤقتا وغير مؤجش مؤقتا، حيث ستفقد ما هو في المخزن المؤقت الخاص بك عندما لا تدفعه مع Fflush ().
نعم. عندما تحتاج إلى مقبض منخفض المستوى.
على أنظمة التشغيل UNIX، يمكنك عموما تبادل مقابض الملفات والمقابس.
أيضا، تصنع مقابض منخفضة المستوى لتحسين توافق ABI من مؤشرات الملفات.
عادة، يجب أن تفضل استخدام المكتبة القياسية (FOPEN). ومع ذلك، هناك مناسبات حيث ستحتاج إلى استخدام فتح مباشرة.
مثال واحد يتبادر إلى الذهن هو العمل حول خطأ في إصدار أقدم من سولاريس الذي جعل Fopen فشل بعد 256 ملفات مفتوحة. كان هذا لأنهم يستخدمون char غير موقعة لحقل FD في تنفيذ ملفات الهيكل بدلا من int. لكن هذه كانت حالة محددة للغاية.
اقرأ() & اكتب() استخدم I / O غير معروف. فيفاد: واصف ملف صحيح)
fraeb () & fwrite () استخدام المخزن المؤقت I / O. فيملف* مؤشر الهيكل)
البيانات الثنائية مكتوبة إلى أنبوب مع اكتب() ربما لا تكون قادرة على قراءة البيانات الثنائية مع fraeb (), ، بسبب محاذاة البايت، والأحجام المتغيرة، إلخ. انها تبادل لاطلاق النار حماقة.
يستخدم معظم رمز برنامج تشغيل الجهاز منخفض المستوى مكالمات I / O غير مقيدة.
يستخدم معظم مستوى التطبيق I / O مخزن مؤقتا.
استخدام ملف* ووظائفها المرتبطة بها على ما يرام على أساس الجهاز بواسطة الجهاز: ولكن يتم فقد قابلية النقل على بنية أخرى في قراءة البيانات الثنائية وكتابةها. FWRite () مخزنة مؤقتا I / O ويمكن أن يؤدي إلى نتائج غير موثوق بها إذا كتبت بنية 64 بت وتشغيلها على 32 بت؛ أو (ويندوز / لينكس). معظم OSS لها وحدات ماكرو التوافق ضمن الكود الخاص بها لمنع هذا.
بالنسبة لقدرة I / O منخفضة المستوى اقرأ() و اكتب() ضمان القراءة الثنائية نفسها ويكتب عند تجميعها على الهندسة المختلفة. الشيء الأساسي هو اختيار طريقة واحدة أو غيرها وتكون متسقة حولها، في جميع أنحاء الجناح الثنائي.
<stdio.h> // mostly FILE* some fd input/output parameters for compatibility
// gives you a lot of helper functions -->
List of Functions
Function Description
───────────────────────────────────────────────────────────────────
clearerr check and reset stream status
fclose close a stream
fdopen stream open functions //( fd argument, returns FILE*) feof check and reset stream status
ferror check and reset stream status
fflush flush a stream
fgetc get next character or word from input stream
fgetpos reposition a stream
fgets get a line from a stream
fileno get file descriptor // (FILE* argument, returns fd)
fopen stream open functions
fprintf formatted output conversion
fpurge flush a stream
fputc output a character or word to a stream
fputs output a line to a stream
fread binary stream input/output
freopen stream open functions
fscanf input format conversion
fseek reposition a stream
fsetpos reposition a stream
ftell reposition a stream
fwrite binary stream input/output
getc get next character or word from input stream
getchar get next character or word from input stream
gets get a line from a stream
getw get next character or word from input stream
mktemp make temporary filename (unique)
perror system error messages
printf formatted output conversion
putc output a character or word to a stream
putchar output a character or word to a stream
puts output a line to a stream
putw output a character or word to a stream
remove remove directory entry
rewind reposition a stream
scanf input format conversion
setbuf stream buffering operations
setbuffer stream buffering operations
setlinebuf stream buffering operations
setvbuf stream buffering operations
sprintf formatted output conversion
sscanf input format conversion
strerror system error messages
sys_errlist system error messages
sys_nerr system error messages
tempnam temporary file routines
tmpfile temporary file routines
tmpnam temporary file routines
ungetc un-get character from input stream
vfprintf formatted output conversion
vfscanf input format conversion
vprintf formatted output conversion
vscanf input format conversion
vsprintf formatted output conversion
vsscanf input format conversion
لذلك للاستخدام الأساسي، أود شخصيا استخدام ما ورد أعلاه دون خلط التعابير أكثر من اللازم.
على نقيض ذلك،
<unistd.h> write()
lseek()
close()
pipe()
<sys/types.h>
<sys/stat.h>
<fcntl.h> open()
creat()
fcntl()
all use file descriptors.
هذه توفر التحكم في الحبيبات الجميلة على القراءة والكتابة بايت (الموصى بها للأجهزة الخاصة والزيفوس (الأنابيب)).
مرة أخرى، استخدم ما تحتاجه، ولكن لا يزال متسقا في التعابير والواجهات الخاصة بك. إذا كانت معظم قاعدة التعليمات البرمجية تستخدم وضع واحد، فاستخدم ذلك أيضا، إلا إذا كان هناك سبب حقيقي لعدم. كلتا المجموعتين من وظائف مكتبة الإدخال / الإخراج موثوقة للغاية واستخدام الملايين من المرات في اليوم.
ملاحظة-- إذا كنت تتداخل في CI / O بلغة أخرى، (Perl، Python، Java، C #، Lua ...) الدفع ما يوصي مطوري هذه اللغات قبل أن تكتب رمز C وإنقاذ نفسك بعض المتاعب.
يتم تخزين FOPEN وابن عمها. فتح، قراءة، والكتابة ليست مخزنة. قد يكون طلبك أو قد يهتم.
لدى FPRINTF و SCANF API الأكثر ثراء يسمح لك بقراءة الملفات النصية المنسقة والكتابة. قراءة والكتابة استخدام المصفوفات الأساسية من البايتات. يجب أن تكون التحويلات والتنسيق مصنوع يدويا.
الفرق بين ملفات الملفات و (الملف *) غير منطقي حقا.
راندي