حالا وقتشه که کار با فایلها در #c را یاد بگیریم. برای این منظور، در این مقاله ما دو کلاس StreamWriter و StreamReader را پوشش میدهیم.
این مقاله، سرفصلی از دوره آموزشی زیر میباشد:
- راه اندازی محیط توسعه
- Data Type ها، Declaration ها و تعریف متغیرها در #C
- عملگرها در #c
- تبدیل نوع های داده ای
- ورودی و خروجی در #c
- کار با رشته ها
- شرطها در #c
- حلقه ها (While، Do-While، For)
- مدیریت خطاها
- Access Modifier ها
- متدها
- کلمات کلیدی Ref و Out
- بازگشت و متدهای بازگشتی
- آرایه ها (آرایه های تک بعدی و چند بعدی)
- کار با فایلها، StreamWriter و StreamReader
- کار با فایلها، File و Directory
اگر می خواهید محتویات کامل این دوره را ببینید ، می توانید بر روی لینک مبانی #c کلیک کنید.
اگر میخواهید سورس کد مثالهای این مقاله را دانلود کنید بر روی لینک سورس کد StreamReader و StreamWriter کلیک کنید.
کلاسهای StreamReader و StreamWriter، کار خواندن و نوشتن بر روی یک فایل را انجام میدهند. هر دوی این کلاسها همچون خیلی از کلاسهای دیگر برای کار با فایلها و دایرکتوری ها در فضای نام System.IO موجود میباشند.
ما در این مقاله، قسمتهای زیر را پوشش میدهیم:
- ایجاد آبجکتها برای StreamWriter و StreamReader
- متدهای StreamReader
- متدهای StreamWriter
- بلاک Using
- نتیجه گیری
ایجاد آبجکتها برای StreamWriter و StreamReader
برای ایجاد آبجکتها برای کلاسهای StreamReader
و StreamWriter
باید از initialization استاندارد برای reference data Type ها استفاده کنیم. ما از چند طریق میتوانیم این initialization را انجام دهیم. اما متداولترین آن، ارائه آدرس فایل مورد نظر است:
1 2 3 4 |
StreamReader readerRelativePath = new StreamReader("test.txt"); StreamReader readerAbsolutePath = new StreamReader("C:\\MyProject\\test.txt"); StreamWriter writerRelativePath = new StreamWriter("test.txt"); StreamWriter writerAbsolutePath = new StreamWriter("C:\\MyProject\\test.txt"); |
همانطور که در کد بالا مشاهده می کنیم ، می توانیم مسیر فایل مورد نظر را به صورت نسبی یا مطلق ارائه دهیم. اگر ما یک مسیر نسبی (فقط نام فایل به همراه پسوند) را ارائه دهیم، ویژوال استودیو، فایل را از داخل پوشه projectName/bin/debug در نظر میگیرد.
متدهای StreamReader
StreamReader دارای متدهای زیادی برای کار با فایلها است، اما ما فقط به چند تا از آنها اشاره میکنیم.
متد ()Read، علامت بعدی در فایل را به عنوان یک عدد صحیح برمیگرداند یا اگر به انتهای فایل رسیده باشد 1- برمیگرداند. ما می توانیم از تبدیل صریح (cast) برای تبدیل آن عدد صحیح به نوع char استفاده کنیم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
static void Main(string[] args) { StreamReader sr = new StreamReader("test.txt"); int x; char ch; x = sr.Read(); while(x != -1) { ch = (char)x; //do stuff here x = sr.Read(); } } |
متد ()ReadLine، کل خط را به عنوان یک رشته برمیگرداند. اگر به انتهای فایل رسیده باشیم null برمیگرداند:
1 2 3 4 5 6 7 8 9 10 11 12 |
static void Main(string[] args) { StreamReader sr = new StreamReader("test.txt"); string line = sr.ReadLine(); while(line != null) { //some coding line = sr.ReadLine(); } } |
متد ()ReadToEnd، کل فایل را در قالب یک رشته برمیگرداند. اگر چیزی برای خواندن وجود نداشته باشد در نتیجه، رشته خالی برمیگرداند.
متد ()Peek، کاراکتر بعدی در فایل را چک میکند. اگر چیزی پیدا نکند 1- برمیگرداند:
1 2 3 4 5 6 7 8 9 10 11 |
static void Main(string[] args) { StreamReader sr = new StreamReader("test.txt"); string line; while(sr.Peek() != -1) { line = sr.ReadLine(); //some coding } } |
متدهای StreamWriter
دوتا از مهمترین متدها برای کلاس StreamWrite، متد Write
() و ()WriteLine
است. با متد ()Write، ما بدون اینکه به خط بعدی برویم یک خط داخل فایل مینویسیم. با متد ()WriteLine، یک خط داخل فایل مینویسیم و به خط بعدی میرویم.
این خیلی مهم است که بعد از اینکه کارمان با ابجکتهای reader یا writer به اتمام رسید، متد ()Close را فراخوانی کنیم.
مثال 1: یک برنامه بنویسید که 5 عدد تصادفی از 1 تا 100 را در فایلی به نام numbers.txt بنویسد. سپس تمام اعداد را از همان فایل خوانده، آنها را چاپ کند و سپس بزرگترین آنها را نیز چاپ نماید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
class Program { public static void WriteToFile(string path) { StreamWriter sw = new StreamWriter(path); Random r = new Random(); //class to generate random numbers for(int i = 1; i <= 5; i++) { sw.WriteLine(r.Next(1,101)); } sw.Close(); } public static void PrintNumbersAndMax(string path) { StreamReader sr = new StreamReader(path); string line = sr.ReadLine(); Console.WriteLine(line); int max = Convert.ToInt32(line); while ((line = sr.ReadLine()) != null) { Console.WriteLine(line); int temp = Convert.ToInt32(line); if(temp > max) { max = temp; } } sr.Close(); Console.WriteLine($"Max number is: {max}"); } static void Main(string[] args) { WriteToFile("numbers.txt"); PrintNumbersAndMax("numbers.txt"); Console.ReadLine(); } } |
همانطور که میبینید ما باید از متد Close برای بستن آبجکتهای reader و writer استفاده کنیم. اما بهترین راه برای انجام این کار، استفاده از بلاک using میباشد.
بلاک Using
بلاک using کمک میکند تا resource مان را مدیریت کنیم. این یک scope را مشخص می کند که ما در آن از resource خود استفاده می کنیم و هنگامی که آن scope را ترک کنیم ، resource مدیریت می شود.
برای استفاده از بلاک using، ما باید کلمه کلیدی using را قرار دهیم، resource را داخل پرانتز ایجاد کنیم و سپس scope بلاک using را با کروشه باز و بسته تعریف کنیم:
1 2 3 4 |
using (Resource creation) { } |
بنابراین ما میتوانیم متدمان از مثال قبلی را مجددا بازنویسی کنیم:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public static void PrintNumbersAndMax(string path) { using (StreamReader sr = new StreamReader(path)) { string line = sr.ReadLine(); Console.WriteLine(line); int max = Convert.ToInt32(line); while ((line = sr.ReadLine()) != null) { Console.WriteLine(line); int temp = Convert.ToInt32(line); if (temp > max) { max = temp; } } Console.WriteLine($"Max number is: {max}"); } } |
در این مثال ، ما از متد Close استفاده نمی کنیم زیرا به محض اینکه اجرا از بدنه بلاک using خارج شود، آبجکت StreamReader خودش مدیریت می شود.
نتیجه گیری
این هم از مبحث فایلها. حالا شما از دانش خوبی برای کار با فایلها در #c برخوردارید.
در مقاله بعدی، ما یاد میگیرم که چطور از کلاسهای File و Directory برای اداره کردن فایلها در #c استفاده کنیم.