قراءة السطر الثاني من ملف نصي ج. العمل مع الملفات النصية في C

لقد تعلمنا بالفعل كيفية كتابة المعلومات في ملف نصي. – إذا لم تتعلم الطريقة، راجع المقال السابق. يتم سردها ووصفها بالتفصيل

ولكن ماذا لو كان الملف موجودًا بالفعل ونحتاج إلى قراءة المعلومات منه للمعالجة؟ ولحسن الحظ، هذا أيضًا بسيط جدًا. اسمحوا لي أن أذكرك أن هناك عدة خيارات لتنفيذ هذه المهمة، وقد وصفت واحدا منها فقط. ما تم وصفه هو الذي يبدو لي شخصيًا لسبب ما أنه الأسهل في الفهم.

#يشمل

إنت الرئيسي ()
{
شار S1 //سوف يقرأ المتغير السلسلة
ifstream في ("C:\\\FromC\\myfile.txt")؛ //افتح الملف لقراءة المعلومات
في >>s1 ; //اقرأ السطر
إغلاق () //إغلاق الملف

cout<إخراج القيمة S1إلى الشاشة
العودة 0 ;
}

إليك أبسط برنامج لقراءة السطر الأول من ملف نصي موجود على طول المسار
C:\\\FromC\\myfile.txt –
وبما أن هذا استمرار للمقال السابق، فقد قررت استخدام الملف الذي أنشأناه هناك. ربما لا ينبغي أن يكون هناك أي صعوبات في هذا.
لكن دعنا نعود إلى الكود. أولا نقوم بفتح الملف لقراءة المعلومات منه، ولهذا نستخدم الأمر com.ifstreamبين قوسين نشير إما إلى اسم الملف أو المسار إلى الملف، كما فعلت. ("C:\\\FromC\\myfile.txt" );
عندما فتحنا ملفًا لقراءة شيء ما منه، أعلنا عن متغير واحد مثل شار -
شار S1
الآن كل ما علينا فعله هو تعيين قيمة السلسلة للمتغير من الملف. نحن نفعل هذا كفريق في
انتبه إلى أقواس الزوايا في >>
في الواقع، كما يجب أن يكون واضحا من التعليقات على كود البرنامج، لكي يقوم المتغير بتعيين قيمة القراءة، يجب أن نكتبها بعد ذلك في >>
في >>s1 ;

لا يبدو أن هذه مهمة صعبة بشكل خاص، خاصة إذا كنت قد أتقنت بالفعل وتعلمت استخدام المواد من المقالة السابقة - كل شيء هو نفسه تمامًا، هناك أمران فقط مختلفان

إنشاء ملف وكتابة معلومات C++ عليه

ofstream خارج (اسم الملف );
خارج<< (السلسلة المراد كتابتها);
خارج.يغلق()؛
=============================

قراءة النص من ملف وطباعة النص على الشاشة في C++

com.ifstream في (اسم الملف)؛
في>> (قراءة السطر);
في.يغلق()؛(أغلق الملف)
============================
لنكتب برنامجًا بسيطًا يقرأ النص المُدخل من لوحة المفاتيح ويكتبه في ملف:

#يشمل
#يشمل

إنت الرئيسي ()
{
\\ 3 خطوط المستقبل
clrscsr(); //مسح الشاشة

cout<<“Wwedi pervuu stroku” ; سين >>أ ; نهاية ;
cout<<“Wwedi wtoruu stroku” ; سين >> ب ; نهاية ;
cout<<“Wwedi tretuu stroku” ; سين >>ج ; نهاية ;
clrscr(); //

/*بدء العمل مع الملف*/
ofstream out ("C:\\\FromC\\myfile.txt"); //فتح ملف للكتابة
خارج<اكتب السطر الأول
خارج<اكتب السطر الثاني
خارج<اكتب السطر الثالث
out.Close(); //إغلاق الملف

// إعادة تعيين المتغيرات

ل (int i = 0 ;i<=255 ;i ++)
(أ =*"" ; ب =*"" ; ج =*"" ;)


إذا تيار في ("C:\\\FromC\\myfile.txt")؛
في >>أ >>ب >>ج ؛ //نقرأ كل سطر جديد في متغير جديد
in. Close(); //إغلاق الملف

/* */

لـ (i =0 ;a !=*“” ;i ++)
{
إذا (i>sizeof(a)) استراحة ؛
cout<

}
cout<<“\n” ; \\

/* */


{
إذا (i>sizeof(b)) استراحة ؛
cout<
}
cout<<“\n” ; \\ نقل المؤشر إلى سطر جديد

/* */

لـ (i =0 ;с !=*“” ;i ++)
{
إذا (i>sizeof(c)) استراحة ؛
cout<<с ;
}

العودة 0 ;
}
===================

في الأمثلة أعلاه هناك واحد من هذا القبيل ضخم عيب. إذا حاولنا إدخال سطر يحتوي على مسافات، فلن يعمل البرنامج كما نحتاج. ربما، ليس أنا فقط، ولكن أيضًا العديد من الأشخاص الآخرين واجهوا هذا الخطأ. لذلك أترك الرمز غير الصحيح حتى تتمكن من رؤية ما قد تواجهه.

نظرًا لعدم وجود كتب في المنزل، بدأت مرة أخرى في البحث على الإنترنت ووجدت الكثير من أنواع الهراء المتطور. لكن بطريقة ما وجدت حلاً لمشكلتي.
لقد ساعدني أن أقرأ ذلك coutيدعم أساليبه. وعلى الإنترنت، تتجه جميع النصائح نحو استخدام الوظيفة com.getlineولحسن الحظ، اكتشفت كيفية استخدام هذه الوظيفة بسرعة كبيرة ثم استخدمتها في الكود.
بشكل عام، من الجدير بالذكر ووصف هذه الوظيفة، لكن حتى الآن لا أفهمها حقًا، أفهم فقط أنه يجب استخدامها وأفهم كيف، لذلك سأقدم مثالًا أكثر صحة لبرنامجنا قيد التطوير :

#يشمل
#يشمل

إنت الرئيسي ()
{
شار أ، ب، ج؛ \\ 3 خطوط المستقبل
clrscsr(); //مسح الشاشة

/* أدخل قيم المتغيرات*/

cout<<“Wwedi pervuu stroku” ; cin.getline(a,sizeof(a));نهاية ;
cout<<“Wwedi wtoruu stroku” ; cin.getline(a,sizeof(b));نهاية ;
cout<<“Wwedi tretuu stroku” ; cin.getline(a,sizeof(c));نهاية ;
clrscr(); //بعد إدخال القيم، تم مسح الشاشة

/*بدء العمل مع الملف*/
ofstream out ("C:\\\FromC\\myfile.txt"); //فتح ملف للكتابة
خارج<
اكتب السطر الأول
خارج<اكتب السطر الثاني
خارج<اكتب السطر الثالث
out.Close(); //إغلاق الملف

// إعادة تعيين المتغيرات

ل (int i = 0 ;i<=255 ;i ++)
(أ =*"" ; ب =*"" ; ج=*"" ;)

/*متابعة العمل مع الملف*/

إذا دفق في ("C:\\\FromC\\myfile.txt")؛
in.getline(a,sizeof(a));// أ
in.getline(b,sizeof(b));// قراءة سطر في متغير ب
in.getline(c,sizeof(c)); // قراءة سطر في متغير ج
in. Close(); //إغلاق الملف

/* نقرأ السطر الأول حرفًا بحرف ونعرضه على الشاشة */

لـ (i =0 ;a !=*“” ;i++)
{
إذا (i>sizeof(a)) استراحة ؛
cout<

}
cout<<“\n” ; \\ نقل المؤشر إلى سطر جديد

/* نقرأ السطر الثاني حرفًا بحرف ونعرضه على الشاشة */

لـ (i =0 ;b !=*“” ;i ++)
{
إذا (i>sizeof(b)) استراحة ؛
cout<
}
cout<<“\n” ; \\ نقل المؤشر إلى سطر جديد

/* نقرأ السطر الثالث حرفًا بحرف ونعرضه على الشاشة */

لـ (i =0 ;с !=*“” ;i++)
{
إذا (i>حجم (ج)) استراحة ؛
cout<<с[i];
}

getch(); \\في انتظار الضغط على مفتاح Enter
العودة 0 ;
}
===================

تصف هذه المادة مثالاً لقراءة المعلومات حرفًا بحرف. بما أنني لم أصف العمل مع متغيرات مثل شار، فقد يواجه المبتدئين بعض الإزعاج في فهم الكود. أنا فقط لم أكن أعرف ما هو نوع شارلديه بعض الخصائص ويعتقد أن كل شيء كان أبسط. لذلك يمكن قراءة بعض اللحظات غير المفهومة للبرنامج أعلاه في المقالة التالية العمل مع شار V C++ للمبتدئين

بخلاف ذلك، يجب أن يكون المثال الموضح لكيفية قراءة الأسطر من ملف نصي في لغة C++ سهل الوصول إليه ومفهومًا تمامًا. هذا ليس خيار التنفيذ الأمثل في الوقت الحالي، وقد فاتني بعض النقاط المهمة، ولكن بما أننا بدأنا في تعلم لغة C++، فهذا يكفي تمامًا في الوقت الحالي. في وقت لاحق، ربما سأصل إلى ما فاتني، ولكن الآن أحتاج إلى إدراك الأكثر ضرورة فقط.

إذا فهمنا أنا وأنت هذه المادة، فهذا يعني أننا خطونا خطوة صغيرة نحو احترافنا.

ملحوظة:
استراحة ؛– هذا هو الأمر الذي يخرج من الحلقة. لدينا إذا كان عداد الدورة ليصبح أكبر من الحجم المعلن للمتغير شار,ثم نخرج من الحلقة بالقوة
!= – هذا هو الشرط الذي وضعناه. ويشار إلى هذا الشرط بعدم المساواة
إذا (أ ! = ب)- يقرأ كما لو ألا يساوي ب

نهاية ; -يؤدي هذا إلى نقل المؤشر إلى سطر جديد داخل وحدة التحكم (بقدر ما أفهم)
هذا الأمر مشابه ل "\ن"

ملفات نصية

دعونا نلقي نظرة على العمل مع ملف نصي في لغة C باستخدام مثال. قم بإنشاء ملف نصي على محرك الأقراص C يسمى TextFile.txt. اكتب الأسطر التالية في هذا الملف:

سلسلة_1 123 سلسلة_11، 456
String_2
سلسلة_3

احفظ الملف.

وهذا هو الكود الخاص ببرنامج C الذي يفتح ملفنا ويقرأ الأسطر منه:

/* *المؤلف: @author Subbotin B.P..h> #include #define LEN 50 int main(void) ( puts("عمليات الملف النصي"); char cArray; FILE *pTextFile = fopen("C:\\TextFile.txt", "r"); if(pTextFile == NULL) ( puts("Problems"); return EXIT_FAILURE; ) while(fgets(cArray, LEN, pTextFile) != NULL) ( printf("%s", cArray); ) f Close(pTextFile); return EXIT_SUCCESS;

لفتح ملف نصي في لغة C، استخدم الدالة fopen:

FILE *pTextFile = fopen("C:\\TextFile.txt", "r");

تشير الوسيطة الأولى للدالة fopen إلى ملف، بينما تشير الوسيطة الثانية إلى أن الملف مفتوح للقراءة منه.

نقرأ السطور باستخدام الدالة fgets :

fgets(cArray, LEN, pTextFile);

تشير الوسيطة الأولى للدالة fgets إلى مصفوفة أحرف سيتم تخزين السلاسل المستلمة فيها، والوسيطة الثانية هي الحد الأقصى لعدد الأحرف المراد قراءتها، والثالثة هي ملفنا.

بعد الانتهاء من العمل مع الملف، تحتاج إلى إغلاقه:

fClose(pTextFile);

نحصل على:

تظهر الحروف الروسية أيضًا في السطور.

بالمناسبة، لقد صنعت هذا البرنامج في Eclipse. يمكنك معرفة كيفية العمل مع C/C++ في Eclipse.

لذلك، قمنا بفتح وقراءة البيانات من ملف نصي.

سنتعلم الآن كيفية إنشاء ملف نصي برمجيًا وكتابة البيانات إليه.

/* المؤلف: @author Subbotin B.P..h> #include int main(void) ( FILE *pTextFile = fopen("C:\\TextFileW.txt", "w"); char *cString = "هذه سلسلة"; char cNewLine = "\n"; int nVal = 123 ; if(pTextFile == NULL) ( puts("Problems"); return EXIT_FAILURE; ) fprintf(pTextFile, "%s%c, cString, cNewLine);

قم بإنشاء ملف نصي لكتابة البيانات إلى:

FILE *pTextFile = fopen("C:\\TextFileW.txt", "w");

إذا كان الملف موجودا بالفعل، سيتم فتحه وحذف جميع البيانات منه.

تتم كتابة C-string cString والرقم nVal بواسطة البرنامج إلى ملف نصي. cNewLine هو ببساطة سطر جديد.

نكتب البيانات في ملف نصي باستخدام الدالة fprintf:

fprintf(pTextFile, "%s%c", cString, cNewLine);

الوسيطة الأولى هنا هي ملفنا، والثانية هي سلسلة التنسيق، والثالثة أو أكثر هي عدد الوسائط المطلوبة لهذا التنسيق.

- المقارنة لتحديد المساواة أو عدم المساواة.

الغرض العملي من التعداد هو تعريف مجموعة من الثوابت الرمزية المميزة من نوع عدد صحيح.

مثال على استخدام المتغيرات المذكورة:

mo=1, tu, we, th, fr, sa, su ) أيام;

يضع("أدخل يوم الأسبوع (من 1 إلى 7) :"); scanf("%d", &t_day);

w_day = su; ابدأ = مو؛

النهاية = w_day -t_day;

printf("\n يوم الاثنين هو %d يوم في الأسبوع، \ وهو الآن يوم %d. \n\

حتى نهاية الأسبوع %d يوم (أيام). "، البداية، t_day، النهاية)؛

نتيجة البرنامج: أدخل يوم الأسبوع (من 1 إلى 7): 2

الاثنين هو اليوم الأول من الأسبوع، والآن هو اليوم الثاني. هناك 5 أيام (أيام) حتى نهاية الأسبوع.

18. الملفات بلغة C

الملف عبارة عن مجموعة من البيانات الموجودة على وسائط خارجية ويتم أخذها في الاعتبار أثناء المعالجة ككل واحد. تحتوي الملفات على بيانات مخصصة للتخزين على المدى الطويل.

هناك نوعان من الملفات: نصية وثنائية. الملفات النصية عبارة عن سلسلة من أحرف ASCII ويمكن عرضها وتحريرها باستخدام أي محرر نصوص.

الملفات الثنائية (الثنائية) هي سلسلة من البيانات، يتم تحديد بنيتها بواسطة البرنامج.

تحتوي لغة C على مجموعة كبيرة من الوظائف للعمل مع الملفات، معظمها موجود في مكتبات stdio.h وio.h.

18.1. فتح ملف

يتم تعيين اسم منطقي داخلي لكل ملف، والذي يتم استخدامه لاحقًا عند الوصول إليه. الاسم المنطقي (معرف الملف) ​​هو

المؤشر إلى الملف، أي. إلى منطقة الذاكرة التي تحتوي على كافة المعلومات الضرورية حول الملف. تنسيق إعلان مؤشر الملف كما يلي:

ملف * مؤشر للملف؛

FILE - معرف نوع البنية الموضح في المكتبة القياسية

stdio.h وتحتوي على المعلومات التالية:

نوع البنية(

- عدد البايتات غير المقروءة المتبقية في المخزن المؤقت؛

حجم المخزن المؤقت المعتاد هو 512 بايت؛ بمجرد المستوى = 0

تتم قراءة كتلة البيانات التالية في المخزن المؤقت من الملف؛

- علامة حالة الملف - القراءة والكتابة والإلحاق؛

- واصف الملف، أي الرقم الذي يحدد رقمه

عقد حرف غير موقعة؛

- حرف غير منقول، أي. ungetc-character;

- حجم المخزن المؤقت الوسيط الداخلي؛

المخزن المؤقت شار غير الموقعة؛

– قيمة المؤشر للوصول داخل المخزن المؤقت، أي

يحدد بداية المخزن المؤقت، بداية السطر، أو القيمة الحالية

قيمة المؤشر داخل المخزن المؤقت حسب الوضع

أماه التخزين المؤقت؛

غير موقعة شار *curp؛

– القيمة الحالية للمؤشر للوصول داخل

فيرا، أي. يحدد الموقع الحالي في المخزن المؤقت للتبادل

مع البرنامج؛

غير موقعة؛

- إشارة الملف المؤقت؛

- علامة عند العمل مع ملف؛

) ملف؛

قبل البدء في العمل مع الملف، أي. لتتمكن من قراءة المعلومات أو كتابتها في ملف، يجب فتحه للوصول إليه. لهذا الغرض يتم استخدام الوظيفة عادة

FILE* fopen(char* file_name, char* mode);

فهو يأخذ تمثيلاً خارجيًا - الاسم الفعلي للملف الموجود على وسيط (قرص مرن، محرك أقراص ثابتة) ويطابقه باسم منطقي.

الاسم المادي، أي. يتم تحديد اسم الملف والمسار إليه بواسطة المعلمة الأولى

– سطر، على سبيل المثال، “a:Mas_dat.dat” – ملف اسمه Mas_dat.dat موجود على قرص مرن، “d:\\work\\Sved.txt” – ملف اسمه Sved.txt موجود على القرص الصلب القيادة في دليل العمل .

انتباه! تتم كتابة الشرطة المائلة العكسية (\)، كحرف خاص، مرتين في السطر.

عند الفتح الناجح، تقوم الدالة fopen بإرجاع مؤشر إلى الملف (يشار إليه فيما بعد بمؤشر الملف). عند حدوث خطأ، يتم إرجاع NULL. يحدث هذا الموقف عادةً عندما يتم تحديد المسار إلى الملف الذي سيتم فتحه بشكل غير صحيح. على سبيل المثال، إذا حددت في فصل العرض بجامعتنا مسارًا محظورًا للكتابة (عادةً ما يكون d:\work\ مسموحًا به).

المعلمة الثانية عبارة عن سطر يحدد وضع الوصول إلى الملف:

ث – الملف مفتوح للكتابة؛ إذا لم يكن هناك ملف بالاسم المحدد، فسيتم إنشاؤه؛ إذا كان هذا الملف موجودا، فسيتم إتلاف المعلومات السابقة قبل فتحه؛

r - يفتح الملف للقراءة فقط؛ إذا لم يكن هناك مثل هذا الملف، يحدث خطأ؛

أ – يتم فتح الملف لإضافة معلومات جديدة إلى النهاية؛

r+ – الملف مفتوح لتحرير البيانات – من الممكن كتابة وقراءة المعلومات؛

w+ – نفس الشيء بالنسبة لـ r+;

a+ - كما هو الحال بالنسبة لـ a، يمكن إجراء الكتابة فقط في أي مكان في الملف؛ قراءة الملفات متاحة أيضًا؛

t - يتم فتح الملف في الوضع النصي؛ ب - يتم فتح الملف في الوضع الثنائي.

يختلف وضع النص عن الوضع الثنائي حيث أنه عند فتح ملف كنص، يتم استبدال زوج الأحرف "تغذية السطر" و"سطر الإرجاع" بحرف واحد: "تغذية السطر" لجميع وظائف كتابة البيانات إلى الملف وبالنسبة لجميع وظائف الإخراج، تم الآن استبدال حرف "تغذية السطر" بحرفين: "تغذية السطر" و"سطر الإرجاع".

افتراضيًا، يتم فتح الملف في الوضع النصي. مثال: ملف *f؛ - تم الإعلان عن مؤشر للملف f؛

f = fopen("d:\\work\\Dat_sp.cpp", "w"); - يتم فتح ملف بالاسم المنطقي f، والذي له الاسم الفعلي Dat_sp.cpp، الموجود على محرك الأقراص d، في دليل العمل، للكتابة؛ أو باختصار أكثر

FILE *f = fopen("d:\\work\\Dat_sp.cpp", "w");

18.2. إغلاق ملف

بعد العمل مع ملف، يجب إغلاق الوصول إليه. يتم ذلك عن طريق الدالة int fclose (مؤشر الملف). على سبيل المثال، من المثال السابق يتم إغلاق الملف بهذا الشكل: f Close (f)؛

لإغلاق ملفات متعددة، يتم تقديم وظيفة تم تعريفها على النحو التالي: void f Closeall (void)؛

إذا كنت بحاجة إلى تغيير وضع الوصول لملف ما، فيجب عليك أولاً إغلاق الملف ثم فتحه مرة أخرى، ولكن مع حقوق وصول مختلفة. للقيام بذلك، استخدم الدالة القياسية:

FILE* freopen (char*file_name, char *mode, FILE *file_pointer);

تقوم هذه الوظيفة أولاً بإغلاق الملف المعلن file_pointer(كما تفعل الدالة fopen)، ثم يفتح الملف باسم file_name والأذونات "mode".

تتمتع لغة C بالقدرة على العمل مع الملفات المؤقتة المطلوبة فقط أثناء تشغيل البرنامج. في هذه الحالة يتم استخدام الدالة

ملف * tmpfile (باطل)؛

الذي يقوم بإنشاء ملف مؤقت على القرص بحقوق الوصول "w+b" بعد اكتمال البرنامج أو بعد إغلاق الملف المؤقت، يتم حذفه تلقائيًا.

18.3. الكتابة - قراءة المعلومات

يمكن تقسيم جميع الإجراءات الخاصة بقراءة البيانات وكتابتها إلى ملف إلى ثلاث مجموعات: عمليات الإدخال والإخراج لكل حرف؛ عمليات الإدخال/الإخراج سطرًا تلو الآخر؛ منع عمليات الإدخال/الإخراج.

دعونا نلقي نظرة على الوظائف الرئيسية المستخدمة في كل مجموعة من مجموعات العمليات الثلاث هذه.

الإدخال/الإخراج لكل حرف على حدة

في وظائف الإدخال/الإخراج لكل حرف على حدة، يتم تلقي حرف واحد من ملف أو يتم إرسال حرف واحد إلى ملف:

صف الإدخال/الإخراج

يتم نقل وظائف الإدخال/الإخراج من ملف أو إلى

كتلة الإدخال/الإخراج

تعمل وظائف الإدخال/الإخراج على الكتل بأكملها

معلومة:

كثافة العمليات (void*p, intsize,

- يقرأ n كتل بحجم بايت لكل منها من الملف

كثافة العمليات ن، ملف * و)

la f إلى منطقة الذاكرة بالمؤشر p (مطلوب

int fwrite (void*p, intsize,

تخصيص الذاكرة مسبقًا للكتلة المراد قراءتها)؛

- يكتب n كتل بحجم بايت لكل منها

كثافة العمليات ن، ملف * و)

منطقة الذاكرة مع المؤشر p للملف f.

يتم إنتاج الإدخال/الإخراج المنسق بواسطة الوظائف.

آخر تحديث: 31/10/2015

فصل دفق الملفاتيمثل إمكانيات القراءة من ملف والكتابة إلى ملف. يسمح لك بالعمل مع كل من الملفات النصية والملفات الثنائية.

ولنتعرف على أهم خصائصه وطرقه:

    خاصية الطول: تُرجع طول الدفق بالبايت

    خاصية الموضع: إرجاع الموضع الحالي في الدفق

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

    • المصفوفة - مصفوفة من البايتات حيث سيتم وضع البيانات المقروءة من الملف

      يمثل الإزاحة الإزاحة بالبايت في المصفوفة التي سيتم وضع بايتات القراءة فيها

      العد - الحد الأقصى لعدد البايتات المراد قراءتها. إذا كان هناك عدد أقل من البايتات في الملف، فستتم قراءتها جميعًا.

    طريقة بحث طويل (إزاحة طويلة، أصل SeekOrigin): يضبط الموضع في الدفق مع إزاحة بعدد البايتات المحدد في معلمة الإزاحة.

    طريقة الكتابة: كتابة البيانات من مصفوفة بايت إلى ملف. يأخذ ثلاث معلمات: الكتابة (صفيف البايت، إزاحة int، عدد int)

    • المصفوفة - مصفوفة من البايتات التي سيتم كتابة البيانات منها إلى الملف

      الإزاحة - الإزاحة بالبايت في المصفوفة من حيث تبدأ كتابة البايتات في الدفق

      العد - الحد الأقصى لعدد البايتات المراد كتابتها

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

في الوقت نفسه، عند العمل مع ملفات ثنائية مختلفة لها بنية معينة، يمكن أن يكون FileStream مفيدًا جدًا لاستخراج أجزاء معينة من المعلومات ومعالجتها.

دعونا نلقي نظرة على مثال للقراءة والكتابة في ملف نصي:

Console.WriteLine("أدخل سطرًا للكتابة في الملف:"); نص السلسلة = Console.ReadLine(); // الكتابة إلى ملف باستخدام (FileStream fstream = new FileStream(@"C:\SomeDir\noname\note.txt"، FileMode.OpenOrCreate)) ( // تحويل السلسلة إلى بايت byte array = System.Text.Encoding. Default.GetBytes(text); // كتابة مصفوفة من البايتات إلى ملف fstream.Write(array, 0, array.Length); Console.WriteLine("النص المكتوب في الملف"); fstream = File.OpenRead(@"C:\SomeDir\noname\note.txt")) ( // تحويل السلسلة إلى بايت byte array = new byte; // قراءة البيانات fstream.Read(array, 0, array. الطول)؛ // فك تشفير البايتات إلى سلسلة نصية textFromFile = System.Text.Encoding.Default.GetString(array); Console.WriteLine("نص من الملف: (0)"، textFromFile ) Console.ReadLine();

دعونا ننظر إلى هذا المثال. تستخدم كل من القراءة والكتابة عبارة الاستخدام. لا ينبغي الخلط بين هذا البيان والتعليمة use، التي تتضمن مساحات الأسماء في بداية ملف التعليمات البرمجية. تسمح لك عبارة الاستخدام بإنشاء كائن في كتلة من التعليمات البرمجية، وعند الانتهاء منها يتم استدعاء طريقة التخلص من هذا الكائن، وبالتالي يتم تدمير الكائن. في هذه الحالة، يعمل المتغير fstream ككائن من هذا القبيل.

يتم إنشاء كائن fstream بطريقتين مختلفتين: من خلال المنشئ ومن خلال إحدى الطرق الثابتة لفئة الملف.

هنا يتم تمرير معلمتين إلى المنشئ: مسار الملف وتعداد FileMode. يشير هذا التعداد إلى وضع الوصول إلى الملف ويمكن أن يأخذ القيم التالية:

    إلحاق: في حالة وجود الملف، يتم إلحاق النص بنهاية الملف. إذا كان الملف غير موجود، يتم إنشاؤه. الملف مفتوح للكتابة فقط.

    إنشاء: يتم إنشاء ملف جديد. إذا كان هذا الملف موجودًا بالفعل، فسيتم استبداله

    CreateNew: يتم إنشاء ملف جديد. إذا كان هذا الملف موجودًا بالفعل، فسيقوم التطبيق بطرح خطأ

    فتح: فتح ملف. إذا كان الملف غير موجود، فسيتم طرح استثناء

    OpenOrCreate: إذا كان الملف موجودًا، يتم فتحه، وإذا لم يكن موجودًا، يتم إنشاء ملف جديد

    اقتطاع: إذا كان الملف موجودًا، فسيتم استبداله. الملف مفتوح للكتابة فقط.

تقوم طريقة OpenRead الثابتة لفئة File بفتح ملف للقراءة وإرجاع كائن FileStream.

يحتوي مُنشئ فئة FileStream أيضًا على عدد من التحميلات الزائدة التي تسمح لك بتخصيص الكائن الذي يتم إنشاؤه بشكل أكثر دقة. يمكن الاطلاع على كل هذه الإصدارات على MSDN.

تستخدم كل من الكتابة والقراءة كائن الترميز Encoding.Default من مساحة الاسم System.Text. في هذه الحالة، نستخدم طريقتين من أساليبها: GetBytes للحصول على مصفوفة بايت من سلسلة وGetString للحصول على سلسلة من مصفوفة بايت.

ونتيجة لذلك، تتم كتابة السلسلة التي أدخلناها إلى الملف note.txt. في الأساس، هذا ملف ثنائي (وليس ملفًا نصيًا)، على الرغم من أنه إذا كتبنا سطرًا فقط فيه، فيمكننا عرض هذا الملف في نموذج يمكن قراءته بواسطة الإنسان عن طريق فتحه في محرر نصوص. ومع ذلك، إذا كتبنا بايتات عشوائية فيه، على سبيل المثال:

Fstream.WriteByte(13); fstream.WriteByte(103);

ثم قد نواجه مشاكل في فهم ذلك. لذلك، تم تصميم فئات منفصلة للعمل مباشرة مع الملفات النصية - StreamReader وStreamWriter.

الوصول العشوائي إلى الملفات

غالبًا ما تمثل الملفات الثنائية بنية محددة. ومن خلال معرفة هذه البنية، يمكننا أخذ المعلومات الضرورية من الملف، أو على العكس من ذلك، كتابة مجموعة معينة من البايتات في مكان معين في الملف. على سبيل المثال، في ملفات wav، تبدأ البيانات الصوتية نفسها بـ 44 بايت، وما يصل إلى 44 بايت توجد بيانات وصفية مختلفة - عدد القنوات الصوتية، وتردد أخذ العينات، وما إلى ذلك.

باستخدام طريقة Seek()، يمكننا التحكم في موضع مؤشر الدفق، بدءًا من قراءة الملف أو كتابته. تأخذ هذه الطريقة معلمتين: الإزاحة والموضع في الملف. يتم وصف الموضع في الملف بثلاث قيم:

    SeekOrigin.Begin : بداية الملف

    SeekOrigin.End : نهاية الملف

    SeekOrigin.Current: الموضع الحالي في الملف

يتم إزاحة مؤشر الدفق الذي تبدأ منه القراءة أو الكتابة للأمام عن طريق الإزاحة بالنسبة للموضع المحدد كمعلمة ثانية. يمكن أن تكون الإزاحة سالبة، ثم يتحرك المؤشر للخلف، وإذا كانت موجبة، ثم للأمام.

دعونا نلقي نظرة على مثال:

باستخدام System.IO؛ باستخدام System.Text؛ فئة البرنامج ( static void Main(string args) ( string text = "hello World"؛ // الكتابة إلى ملف باستخدام (FileStream fstream = new FileStream(@"D:\note.dat"، FileMode.OpenOrCreate)) ( / / تحويل السلسلة إلى بايت input = Encoding.Default.GetBytes(text); // كتابة مصفوفة من البايتات إلى ملف fstream.Write(input, 0, input.Length); Console.WriteLine("النص المكتوب إلى الملف" ); حرك المؤشر إلى نهاية الملف، بمقدار خمس بايت إلى نهاية الملف fstream.Seek(-5, SeekOrigin.End); // ناقص 5 أحرف من نهاية الدفق // قراءة أربعة أحرف من إخراج بايت الموضع الحالي = بايت جديد (output, 0,put.Length); // فك تشفير البايتات إلى سلسلة نصية textFromFile = Encoding.Default.GetString(output Console.WriteLine("نص من الملف: (0)" , textFromFile); في الملف سلسلة الكلمة إلى منزل الكلمة returnText = "house"; GetBytes(replaceText, 0, input.Length);

// قراءة الملف بأكمله // إرجاع المؤشر إلى بداية الملف fstream.Seek(0, SeekOrigin.Begin);

الإخراج = بايت جديد؛

fstream.Read(output, 0,output.Length);

// فك تشفير البايتات إلى سلسلة نصية textFromFile = Encoding.Default.GetString(output);

Console.WriteLine("نص من الملف: (0)"، textFromFile); // مرحبا بالمنزل ) Console.Read();

))

إخراج وحدة التحكم:

نص مكتوب إلى ملف نص من ملف: Worl نص من ملف: hello house

FileStream fstream = null; حاول ( fstream = new FileStream(@"D:\note3.dat"، FileMode.OpenOrCreate)؛ // العمليات مع الدفق)catch(Exception ex) () أخيرًا (if (fstream != null) fstream.Close() ;)

إذا لم نستخدم البنية use، فسنحتاج إلى استدعاء طريقة Close() بشكل صريح: fstream.Close()

لا تتوافق آلية الإدخال/الإخراج التي تم تطويرها بواسطة , مع النمط المقبول عمومًا للبرمجة الموجهة للكائنات اليوم، بالإضافة إلى أنها تستخدم بشكل كبير عمليات المؤشر التي تعتبر غير آمنة في بيئات تنفيذ التعليمات البرمجية الحديثة والآمنة. البديل عند تطوير تطبيقات التطبيقات هو آلية فئات الإدخال/الإخراج القياسية التي يوفرها معيار لغة C++.

فتح الملفات

الفئات الأكثر استخدامًا هي ifstream للقراءة، وofstream للكتابة، وfstream لتعديل الملفات.

جميع فئات الإدخال/الإخراج المترابطة مشتقة بشكل غير مباشر من السلف المشترك ios، وترث وظائفها بالكامل. وبالتالي، يتم تحديد وضع فتح الملف بواسطة عضو البيانات من النوع open_mode الذي تم تعريفه على النحو التالي:

التعداد open_mode (التطبيق، الثنائي، داخل، خارج، trunc، أكل)؛

فيما يلي القيم المحتملة للأعلام والغرض منها.

على سبيل المثال، لفتح ملف اسمه test.txt لقراءة البيانات في شكل ثنائي، يمكنك كتابة:

ملف ifstream؛ file.open("test.txt", ios::in | ios::binary);

يسمح لك عامل التشغيل المنطقي OR (|) بإنشاء وضع باستخدام أي مجموعة من العلامات. لكي لا تقوم عند فتح ملف عن طريق الإدخال بالكتابة فوق ملف موجود يحمل نفس الاسم عن طريق الخطأ، يجب عليك استخدام النموذج التالي:

ملف أوفستريم؛ file.open("test.txt", ios::out | ios::app);

من المفترض أن يتم تضمين ملف الرأس المقابل في المشروع:

#يشمل

للتحقق مما إذا تم فتح الملف بنجاح، يمكنك استخدام البناء

إذا (!ملف) (//معالجة خطأ فتح الملف)

مشغلي الإدماج والاستخراج

تم تجاوزه في فئات معالجة الملفات عامل الادراج (<<) записывает данные в файловый поток. Как только вы открыли файл для записи, можно записывать в него текстовую строку целиком:

ملف<< "Это строка текста";

يمكنك أيضًا كتابة سلسلة نصية في أجزاء:

ملف<< "Это " << "строка " << "текста";

تنهي عبارة endl إدخال السطر بحرف إرجاع:

ملف<< "Это строка текста" << endl;

باستخدام عامل التضمين، من السهل كتابة قيم المتغيرات أو عناصر المصفوفة في ملف:

ملف Ofstream("Temp.txt"); char buff = "تحتوي مجموعة النص على متغيرات"; إنت فكس = 100؛ تعويم بي = 3.14159؛ ملف<< buff << endl << vx << endl << pi << endl;

نتيجة لتنفيذ التعليمات البرمجية، يتم تشكيل ثلاثة أسطر من الملف النصي Temp.txt:

تحتوي مجموعة النص على متغيرات 100 3.14159

لاحظ أن القيم الرقمية تتم كتابتها في الملف كسلاسل نصية بدلاً من القيم الثنائية.

عامل الاسترجاع(>>) ينتج عنه تأثير معاكس. يبدو أنه لاستخراج الأحرف من ملف Temp.txt المكتوب مسبقًا، ستكتب تعليمات برمجية كما يلي:

ملف ifstream("Temp.txt"); برتقالي شار؛ كثافة العمليات vx؛ تعويم بي؛ ملف >> برتقالي >> vx >> pi;

ومع ذلك، سيتوقف عامل الاستخراج عند أول محدد يواجهه (مسافة، أو علامة تبويب، أو سطر جديد). وبالتالي، عند تحليل الجملة "مصفوفة نص تحتوي على متغيرات"، سيتم كتابة كلمة "نص" فقط في مصفوفة buff، وسيتم تجاهل المسافة، وستصبح كلمة "مصفوفة" هي قيمة متغير vx بأكمله، والكود سوف "ينحرف" التنفيذ مع الانتهاك الحتمي لبنية البيانات. بعد ذلك، عند مناقشة فئة ifstream، سنوضح كيفية تنظيم قراءة الملف بشكل صحيح من المثال السابق.

فئة ifstream: قراءة الملفات

كما يوحي الاسم، تم تصميم فئة ifstream لإدخال دفق ملف. الطرق الرئيسية للفئة مذكورة أدناه. يتم توريث معظمها من فئة istream ويتم تحميلها بشكل زائد لتوسيع الوظيفة الأصلية. على سبيل المثال، يمكن لوظيفة get، اعتمادًا على معلمة الاتصال، قراءة ليس فقط حرفًا واحدًا، ولكن أيضًا مجموعة من الأحرف.

أصبح من الواضح الآن كيف يحتاج المثال السابق إلى التعديل بحيث يعطي استخدام عامل استخراج البيانات النتيجة المتوقعة:

ملف ifstream("Temp.txt"); برتقالي شار؛ كثافة العمليات vx؛ تعويم بي؛ file.getline(buff, sizeof(buff)); الملف >> vx >> بي:

ستقرأ طريقة getline السطر الأول من الملف حتى النهاية، وسيقوم عامل >> بتعيين قيم للمتغيرات.

يوضح المثال التالي إضافة البيانات إلى ملف نصي ثم قراءة الملف بأكمله. يتم استخدام حلقة while(1) بدلاً من while(!file2.eof()) للأسباب التي تمت مناقشتها في .

#يشمل #يشمل باستخدام مساحة الاسم الأمراض المنقولة جنسيا؛ int main() ( ملف ofstream; file.open("test.txt",ios::out|ios::app); if (!file) ( cout<< "File error - can"t open to write data!"; cin.sync(); cin.get(); return 1; } for (int i=0; i<10; i++) file << i << endl; file.close(); ifstream file2; file2.open("test.txt", ios::in); if (!file2) { cout << "File error - can"t open to read data!"; cin.sync(); cin.get(); return 2; } int a,k=0; while (1) { file2 >>أ؛<< a << " "; k++; } cout << endl << "K=" << k << endl; file2.close(); cin.sync(); cin.get(); return 0; }

إذا كان (file2.eof()) استراحة؛

#يشمل #يشمل cout<< str << endl; // вывод прочитанной строки на экран cin.sync(); cin.get(); return 0; }

يعتمد هذا الرمز ضمن نظام التشغيل Windows أيضًا على وجود حرف السطر الجديد في السطر الأخير من الملف؛ وسيكون من الأكثر موثوقية القيام بذلك:

بينما (1) ( if (file.eof()) Break; file.getline(str, sizeof(str)); cout<< str << endl; }

ليست هناك حاجة إلى استدعاءات صريحة لطرق الفتح والإغلاق. في الواقع، يتيح لك استدعاء المنشئ باستخدام الوسيطة فتح الملف فورًا في لحظة إنشاء كائن الملف المترابط:

ملف ifstream("test.txt");

بدلاً من طريقة الإغلاق، يمكنك استخدام عامل الحذف، الذي سيقوم تلقائيًا باستدعاء مدمر كائن الملف وإغلاق الملف. يضمن رمز الحلقة أثناء إجراء عمليات فحص مناسبة لنهاية الملف.

فئة ofstream: كتابة الملفات

تم تصميم فئة ofstream لإخراج البيانات من دفق الملفات. فيما يلي قائمة بالطرق الرئيسية لهذه الفئة.

يعد عامل التضمين الموضح سابقًا مناسبًا لتنظيم الكتابة إلى ملف نصي:

ملف Ofstream("temp.txt"); إذا (! ملف) العودة؛ ل(int i=1; i<=3; i++) file << "Строка " << i << endl; file.close();

الملفات الثنائية

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

يجب أن تكون المعلمة الأولى لطرق الكتابة والقراءة (عنوان كتلة الكتابة/القراءة) من نوع مؤشر الحرف char *، لذلك من الضروري إجراء تحويل صريح لنوع العنوان للبنية void *. تحدد المعلمة الثانية أن الكتل الثنائية للملف لها حجم بايت ثابت بغض النظر عن طول السجل الفعلي. يوفر التطبيق التالي مثالاً على إنشاء البيانات وعرضها في دفتر ملاحظات بسيط. تتم بعد ذلك قراءة إدخالات الملف بالتسلسل وعرضها على وحدة التحكم.

#يشمل #يشمل #يشمل باستخدام مساحة الاسم الأمراض المنقولة جنسيا؛ ملاحظات الهيكل ( // بنية بيانات دفتر الملاحظات char Name؛ // الاسم الكامل char Phone؛ // phone int Age؛ // age )؛ int main() ( setlocale(LC_ALL, "روسي"); الملاحظات Note1= ("الرهيب يوان فاسيليفيتش"، "غير مثبت"، 60)؛ الملاحظات Note2= ("غودونوف بوريس فيدوروفيتش"، "2233-111-095" , 30 ); sizeof (Notes)); // الكتلة الأولى ofile.write((char*)&Note2, sizeof(Notes)); // الكتلة الثانية ofile.write((char*)&Note3, sizeof(Notes)); .Close(); // أغلق الملف المسجل ifstream ifile("Notebook.dat"، ios::binary); // متغير منظم char str; (!ifile.read((char*)&Note, sizeof(Notes)).eof()) ( sprintf(str, "%s\tالهاتف: %s\tAge: %d" , Note.Name, Note.Phone, ملاحظة. العمر)؛<< str << endl; } ifile.close(); // закрыть прочитанный файл cin.sync(); cin.get(); return 0; }

نتيجة لتنفيذ هذا الرمز، يتم تشكيل ملف ثنائي Notebook.dat من ثلاث كتل كل منها 80 بايت (بافتراض أن الأحرف بايت واحد). وبطبيعة الحال، يمكنك استخدام أساليب الترابط الأخرى وتنفيذ أي عمليات على حقول بنية بيانات محددة.

فئة fstream: الوصول العشوائي للملفات

لنفترض أن لدينا 100 إدخال في دفتر ملاحظاتنا، ونريد أن نحسب الرقم 50. بالطبع، يمكنك تنظيم حلقة وقراءة جميع السجلات من الأول إلى السجل المحدد. من الواضح أن الحل الأكثر استهدافًا هو ضبط مؤشر موضع ملف pos مباشرةً على الإدخال 50 والقراءة منه:

Ifstream ifile("Notebook.dat"، ios::binary); int pos = 49 * sizeof(Notes); ifile.seekg(pos); // ابحث عن إدخال ملاحظة الملاحظات الخمسين؛

//ملاحظات - بنية "السجل" الموضحة أعلاه ifile.read((char*)&Note, sizeof(Notes));

تكون عمليات البحث هذه فعالة إذا كان الملف يتكون من سجلات ذات حجم معروف وثابت. لاستبدال محتويات سجل عشوائي، تحتاج إلى فتح دفق الإخراج في وضع التعديل:

Ofstream ofile ("Notebook.dat"، ios::binary | ios::ate); int pos = 49 * sizeof(Notes); ofile searchp(pos); // ابحث عن الإدخال رقم 50 الملاحظات Note50 = ("Yeltsin Bruce Nicolaevich"، "095-222-3322"، 64)؛ ofile.write((char*)&Note, sizeof(Notes)); // استبدال

أخيرًا، من الممكن فتح ملف في وقت واحد للقراءة/الكتابة، باستخدام الطرق الموروثة من فئة التدفق fstream من سابقاتها. نظرًا لأن فئة fstream مشتقة من istream وostream (الوالدان ifstream وofstream على التوالي)، تصبح جميع الطرق المذكورة سابقًا متاحة في التطبيق.

يوضح المثال التالي إعادة ترتيب الإدخالين الأول والثالث في ملف Notebook.dat.

#يشمل #يشمل #يشمل باستخدام مساحة الاسم الأمراض المنقولة جنسيا؛ ملاحظات البنية (اسم char؛ char Phone؛ int Age؛ ); int main() ( setlocale(LC_ALL, "russian"); Notes Note1, Note3; // فتح الملف للقراءة/الكتابة في وقت واحد fstream file("Notebook.dat", ios::binary | ios::in | ios: : out); file.seekg(2 * sizeof(Notes)); // ابحث عن Note3 file.read((char*)&Note3, sizeof(Notes)); // ابحث عن Note1 file.read((char *)&Note1, sizeof(Notes)); file.seekg(0);<== Note3 file.write((char*)&Note3, sizeof(Notes)); file.seekg(2 * sizeof(Notes)); // Note3 <== Note1 file.write((char*)&Note1, sizeof(Notes)); char str; // Считывать и отображать записи в цикле, пока не eof file.seekg(0); // вернуться к началу файла while (!file.read((char*)&Note1, sizeof(Notes)).eof()) { sprintf(str, "%s\tТел: %s\tВозраст: %d", Note1.Name, Note1.Phone, Note1.Age); cout << str << endl; } file.close(); cin.sync(); cin.get(); return 0; }

في مُنشئ كائن الملف، يجب عليك تحديد علامتي ios::in وios::out، مما يسمح بعمليات القراءة والكتابة المتزامنة. ونتيجة لتنفيذ هذا الرمز، سيتم تبديل الإدخالين الأول والثالث في الملف الثنائي Notebook.dat.

هناك أمثلة إضافية حول هذا الموضوع.