اذهب إلى المحتوى
  • 0

كيفية الكتابة والقراءة في لغة السي

أسامة قاسم

السؤال

Recommended Posts

  • 1

لفتح ملف يمكنك استخدام الدالة fopen التي لها الشكل التالي:

FILE *fopen(const char *filename, const char *mode)

تُرجع هذه الدالة مؤشراً على الملف.
حيث أن:
filename: هي اسم الملف المطلوب.

mode يمثل الحالة التي تريد فتح الملف فيها، ويمكننا أن نختار:
            1. "r" للقراءة فقط.
            2. "w" للكتابة فقط (تؤدي إلى إنشاء الملف إذا لم يكن موجوداً).
            3. "a" لإلحاق الملف ببيانات جديدة في نهايته (أي تبدأ الكتابة من نهاية الملف الموجود).
            4. "+r" للقراءة والكتابة في الملف.
            5. "+w" للقراءة والكتابة (تؤدي إلى إنشاء الملف إذا لم يكن موجوداً).
            6. "+a" للقراءة ,والتحديث (تؤدي إلى إنشاء الملف إذا لم يكن موجوداً). ستبدأ القراءة من البداية، لكن
                الكتابة يمكن إلحاقها فقط.
بعد ذلك يمكنك معالجة الملف بالشكل الذي تحتاجه و باستخدام الدوال المناسبة. وهنا غالباً مانحتاج لدوال مثل دالة القراءة ()fread، ودالة الكتابة ()fwrite، ودالة التنقل ()fseek التي تمكننا من التنقل داخل الملف أثناء القراءة أو الكتابة فيه، والدالة ()ftill التي تدلنا على مكان وجودنا داخل الملف.
مثال:

// وذلك لأن الملف غير موجود طبعاً file.txt نتيجة الكود التالي هي إنشاء ملف باسم
// We are in 2021 سنضع في الملف الجملة 
#include <stdio.h>
#include <stdlib.h>
int main () {
   // مؤشر من نوع ملف  
   FILE * fp;
   // فتح الملف
   fp = fopen ("file.txt", "w+");
   // محتوى الملف
   fprintf(fp, "%s %s %s %d", "We", "are", "in", 2021);
   // إغلاق الملف
   fclose(fp);  
   return(0);
}

للكتابة ضمن الملف يمكن أن تستخدم الدالة fwrite:

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)

يستخدم هذا التابع للكتابة بداخل الملف. ويُرجع عدد صحيح يمثل عدد الكلمات التي كُتبت ضمن الملف.
 ptr: مؤشر لمصفوفة العناصر المراد كتابتها.
 size: الحجم بالبايت لكل عنصر تتم كتابته.
 nmemb: عدد العناصر، كل عنصر بحجم البايت.
 stream: مؤشر إلى كائن FILE.
مثال:

#include<stdio.h>
#include<stdib.h>
#include<string.h>
int main () {
   FILE *f=fopen("textfile.txt","w");  // فتح الملف
   char *s = "blabla";  // تعريف النص المطلوب كتابته 
   fwrite(s, sizeof(char), strlen(s), f);
   fclose(f);
   return 0;
}

الوسيط الثاني الذي مررناه إلى الدالة هو sizeof(char) لأن بياناتنا هي عبارة عن مصفوفة محارف وبالتال كل عنصر هو عبارة عن محرف char حجمه 1 بايت وبالتالي سيكون ال size=1 وبما أن أحجام أنواع البيانات قد تختلف من معمارية جهاز إلى آخر فسنضع sizeof(char). أما الوسيط الثالث هو عدد العناصر التي ستتم كتابتها ضمن الملف وهذا يكافئ عدد عناصر مصفوفة المحارف لذا استخدمنا strlen.
للقراءة من الملف نستخدم الدالة fread:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

لاحظ أن وسطاء هذه الدالة لاتختلف عن وسطاء دالة الكتابة مع ملاحظة أن الوسيط ptr هنا سنستخدمه لتخزين النص الذي سنقوم بقراءته.
الآن بعد أن قمنا بالكتابة ضمن الملف في الخطوة السابقة، سنقوم بكتابة كود آخر لقراءة محتويات الملف، لذا سنقوم أولاً بفتح الملف لكن مع تحديد وضع القراءة هذه المرة "r":

FILE *f = fopen("textfile.txt", "r");

ثم سنقوم باستخدام الدالة fread لقراءة المحتويات.
لكن الأمر ليس بهذه البساطة فهنا سنحتاج لتحديد عدد عناصر الملف الذي ستتم قرائته (أقصد ال nmemb)، وذلك لأننا نريد حجز ذاكرة تتسع لما ستتم قرائته، ولمعرفة ذلك سنقوم باستخدام الدالتين ()ftell و ()fseek، حيث سنقوم باستخدام الدالة ()fseek للانتقال من خلالها إلى نهاية الملف:

int fseek(FILE *stream, long int offset, int whence)

 الوسيط الأول هو مؤشر للملف المطلوب. أما الثاني فهو قيمة إزاحة موقع المؤشِّر بالبايت (سنضعها على صفر -سنعرف السبب بعد قليل-).
أما الوسيط الأخير فيأخذ إحدى القيم التالية:

0 أو Seek_SET:
تغيير موقع المؤشِّر إلى قيمة المعامل offset المعطاة بالبايت. أي تنقلنا تماماً إلى قيمة المعامل  الثاني، فلو كان 1 ستنقلنا للمحرف الأول ولو كان 0 -كما في حالتنا- ستنقلنا لبداية الملف، لذا فإن هذه  الحالة لاتخدمنا لأن غايتنا الانتقال لنهاية الملف.

1 أو Seek_CUR:
 تغيير موقع المؤشر إلى قيمة المعامل offset المعطاة بالبايت مضافًا إليها قيمة موقع المؤشِّر  الحالي.  أي بعبارةٍ أوضح تنقلنا من مكاننا الحالي إلى الأمام بمقدار ال offset التي تم تحديدها، وبالتالي إذا وضعنا مكان ال offset ستنقلنا للمحرف الأول، ولو وضعنا 0 فلن يكون لها أي تأثير.  وهذه الحالة أيضاً لاتخدمنا.

2 أو Seek_END:  
تغيير موقع المؤشِّر إلى قيمة موقع نهاية الملف مضافًا إليها قيمة المعامل offset المعطاة بالبايت. أي تنقلنا لنهاية الملف، وهذا مانحتاج إليه. لذا سنستدعي هذه الدالة في مثالنا بالشكل التالي:

  fseek(f, 0, SEEK_END);

الآن بعد أن انتقلنا إلى نهاية الملف أصبح بإمكاننا معرفة حجم الملف من خلال الدالة tell التي ستخبرنا بالموقع الذي نحن فيه، وهذا يكافئ عدد البايتات من بداية الملف، وبالتالي نكون حصلنا على المطلوب.

 unsigned int sz = ftell(f);

الآن بعد معرفة حجم الملف أصبح بإمكاننا حجز ذاكرة تتسع لما ستتم قرائته، لذلك سنستخدم الدالة malloc، وكذلك سنقوم مرة أخرى باستخدام الدالة fseek للعودة إلى بداية الملف:

fseek(f, 0, SEEK_SET);
char *data = (char *)malloc(sz);

ثم نقوم باستدعاء دالة القراءة بالشكل التالي:

fread(data, sizeof(char), sz, f);

وأخيراً طباعة النص:

printf("File has been printed \n%s", data);
free(data);
fclose(f);

الكود كاملاً:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main()
{
    FILE *f = fopen("textfile.txt", "r");
    fseek(f, 0, SEEK_END);
    unsigned int sz = ftell(f);
    fseek(f, 0, SEEK_SET);
    char *data = (char *)malloc(sz);
    fread(data, sizeof(char), sz, f);
    printf("File has been printed \n%s", data);
    free(data);
    fclose(f);
    return 0;
}

 

رابط هذا التعليق
شارك على الشبكات الإجتماعية

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...