ورودی خروجی io
خواندن از صفحهکلید، خواندن و نوشتن پرونده و نوشتن در خروجی خطا.
واردسازی ورودی خروجی
نام آرگومانها شناسهی خود کد است و معادل فارسی ندارد؛ گونهها، کلیدواژهها و نام بستهها با معادل فارسی نوشته میشوند.
بیشتر برنامهها باید چیزی بخوانند و چیزی بنویسند. بستهی ورودی خروجی سادهترین راهها را برای این کار دارد: یک خط از کاربر بخوانید، یک پرونده را یکجا بخوانید یا بنویسید، یا با یک پروندهی باز تکهتکه کار کنید.
تابعهایی که نام پرونده میگیرند (مثل خواندن پرونده) خودشان پرونده را باز میکنند و میبندند. تابعهایی که پرونده* میگیرند با پروندهای کار میکنند که خودتان با سیستم عامل.بازکردن باز کردهاید؛ یادتان باشد آن را با بستن ببندید.
برای کارهای روزمره از ورودی خروجی استفاده کنید. برای اینکه بدانید مسیری وجود دارد یا نه، فهرست پوشهها، پاک کردن یا تغییر نام پرونده به سیستم پرونده بروید؛ برای ساختن مسیر به مسیر و برای خروجی قالببندیشده به قالب بندی.
چند نکته که معمولاً غافلگیر میکند:
- نبودن پرونده اینجا خطا حساب نمیشود.
خواندن پروندهرشتهی تهی برمیگرداند وخط هاوکتوری با یک رشتهی تهی؛ پس پروندهی خالی و پروندهی ناموجود یکجور دیده میشوند. اگر فرقشان برایتان مهم است، اول باسیستم عامل.وجود داردبررسی کنید. - خطها فقط روی
\nجدا میشوند. در پروندهای که با پایان خط ویندوزی ذخیره شده، ته هر خطی کهخط هایاخواندن خطبرمیگرداند یک\rمیماند؛ پیش از مقایسه، خط را پیرایش کنید. - اندازهها بر حسب بایت است، نه حرف. هر حرف فارسی در UTF-8 دو بایت جا میگیرد، پس اگر پروندهی فارسی را تکهتکه میخوانید، ممکن است یک حرف وسط دو تکه نصف شود.
- تابعهای متنی با
رشتهکار میکنند و رشته در نخستین بایت صفر تمام میشود. پروندههای دودویی مثل تصویر همانجا بریده میشوند؛ پس این بسته را برای متن نگه دارید.
خواندن پروندهی تنظیمات
یک پروندهی کوچک به شکل کلید = مقدار رایجترین چیزی است که برنامه هنگام شروع میخواند. خط ها پرونده را به شکل وکتوری از خطها برمیگرداند، پس حلقه فقط باید خطهای خالی و توضیحها را رد کند و هر خط را در نخستین = دو تکه کند. هشدار دربارهی خطهای نادرست با نوشتن خطا با خط جدید به خروجی خطا میرود تا هیچوقت با خروجی اصلی برنامه قاطی نشود.
واردسازی ورودی خروجی
واردسازی رشته
تابع ریشه:
ورودی خروجی.نوشتن پرونده("app.conf"، "# تنظیمات سرور\nدرگاه = ۸۰۸۰\n\nمیزبان = localhost\nکارگرها = ۴\n")
ناپایا تنظیمات := نگاشت {} برگردان نگاشت<رشته، رشته>
دیرکن تنظیمات.آزادکن()
خطها := ورودی خروجی.خط ها("app.conf")
دیرکن خطها.آزادکن()
هر خط در خطها:
اگر خط == "" یا رشته.شروع با(خط، "#"):
گذر
پایان
جای مساوی := رشته.اندیس(خط، "=")
اگر جای مساوی < ۰:
ورودی خروجی.نوشتن خطا با خط جدید("خط بدون '=' کنار گذاشته شد: " + خط)
گذر
پایان
کلید := رشته.پیرایش(رشته.زیررشته(خط، ۰، جای مساوی))
مقدار := رشته.پیرایش(رشته.زیررشته(خط، جای مساوی + ۱، خط.طول() - جای مساوی - ۱))
تنظیمات.درج(کلید، مقدار)
پایان
سرچاپ "میزبان:"، تنظیمات.بگیر("میزبان")
سرچاپ "درگاه:"، تنظیمات.بگیر("درگاه").به صحیح() + ۱
سرچاپ "تنظیمهای خواندهشده:"، تنظیمات.اندازه()
پایانهمهی مقدارها به شکل متن برمیگردند؛ آنها را همانجا که لازم دارید تبدیل کنید، اینجا با به صحیح که رقمهای فارسی را هم میفهمد. خط ها یک وکتور تازه میسازد، پس همان لحظه با دیرکن آزادش کنید. برای قالبهای تودرتو، بهجای تجزیهی دستی سراغ encoding.json یا config بروید.
افزودن به پروندهی گزارش
افزودن به پرونده در هر بار صدا زدن، پرونده را باز میکند، متن را به انتهایش میافزاید و دوباره میبندد؛ پس اگر برنامه وسط کار هم بایستد، گزارش روی دیسک کامل است. برای همین برای گزارش کار و ردگیری رویدادها مناسب است. نوشتن پرونده و افزودن به پرونده هر دو وقتی پرونده باز نشود منفی یک برمیگردانند، و وقتی مسیر از کاربر یا از تنظیمات میآید بهتر است این را بررسی کنید.
واردسازی ورودی خروجی
تابع ثبت(مسیر: رشته، سطح: رشته، پیام: رشته):
اگر ورودی خروجی.افزودن به پرونده(مسیر، "[" + سطح + "] " + پیام + "\n") < ۰:
ورودی خروجی.نوشتن خطا با خط جدید("نوشتن در " + مسیر + " ممکن نیست")
پایان
پایان
تابع ریشه:
مسیر := "app.log"
ورودی خروجی.نوشتن پرونده(مسیر، "")
ثبت(مسیر، "آگاهی"، "سرور راه افتاد")
ثبت(مسیر، "هشدار"، "دیسک ۹۱ درصد پر است")
ثبت(مسیر، "آگاهی"، "به درخواست پاسخ داده شد")
ثبت(مسیر، "خطا"، "پایگاه داده پاسخ نداد")
ناپایا مشکلها := ۰
خطها := ورودی خروجی.خط ها(مسیر)
دیرکن خطها.آزادکن()
هر خط در خطها:
اگر خط.شروع با("[هشدار]") یا خط.شروع با("[خطا]"):
مشکلها++
سرچاپ خط
پایان
پایان
سرچاپ خطها.طول()، "خط،"، مشکلها، "مورد نیاز به بررسی دارد"
پایاناینجا نوشتن پرونده با یک رشتهی خالی، در هر اجرا گزارش را از نو شروع میکند. اگر آن خط را بردارید، گزارش از اجرایی به اجرای بعد بلندتر میشود.
خواندن پروندهی بزرگ تکهتکه
خواندن پرونده و خط ها کل پرونده را در حافظه نگه میدارند. برای پروندهای چندصد مگابایتی، خودتان آن را با سیستم عامل.بازکردن باز کنید و هر بار تعداد ثابتی بایت با خواندن بخوانید. رشتهی خالی یعنی به انتهای پرونده رسیدهاید. پیش از کار با پرونده، آن را با پوچ مقایسه کنید: بازکردن اینطور میگوید که پرونده باز نشد.
واردسازی ورودی خروجی
واردسازی سیستم عامل
واردسازی رشته
تابع ریشه:
ورودی خروجی.نوشتن پرونده("big.txt"، رشته.تکرار("0123456789"، ۲۵))
پ := سیستم عامل.بازکردن("big.txt"، "rb")
اگر پ == پوچ:
ورودی خروجی.نوشتن خطا با خط جدید("باز کردن big.txt ممکن نیست")
برگشت ۱
پایان
دیرکن ورودی خروجی.بستن(پ)
ناپایا جمع := ۰
ناپایا تکهها := ۰
تا درست:
تکه := ورودی خروجی.خواندن(پ، ۶۴ برگردان طبیعی۶۴)
اگر تکه == "":
بشکن
پایان
تکهها++
جمع += تکه.طول()
سرچاپ "تکهی"، تکهها، "اندازهاش"، تکه.طول()، "بایت است"
پایان
سرچاپ جمع، "بایت در"، تکهها، "تکه خوانده شد"
برگشت ۰
پایاناندازه بر حسب بایت است، پس مرز یک تکه ممکن است وسط یک حرف چندبایتی بیفتد؛ متن فارسی دقیقاً همینطور است. اگر فقط بایت میشمارید یا رونوشت میگیرید مهم نیست. اگر خط کامل لازم دارید، مثل بخش بعد با خواندن خط بخوانید.
پردازش پرونده خط به خط
خواندن خط هر بار یک خط را بدون پایان خط برمیگرداند، پس فقط همان خط در حافظه است. سرستون را یک بار بخوانید و بعد تا رسیدن به رشتهی خالیِ انتهای پرونده ادامه دهید.
واردسازی ورودی خروجی
واردسازی سیستم عامل
واردسازی رشته
تابع ریشه:
ورودی خروجی.نوشتن پرونده("sales.csv"، "کالا,تعداد,قیمت\nخودکار,3,12\nدفتر,2,45\nکیف,1,180\n")
پ := سیستم عامل.بازکردن("sales.csv"، "rb")
دیرکن ورودی خروجی.بستن(پ)
سرستون := ورودی خروجی.خواندن خط(پ)
سرچاپ "ستونها:"، سرستون
ناپایا جمع := ۰
ناپایا خط := ورودی خروجی.خواندن خط(پ)
تا خط != "":
ستونها := رشته.تفکیک کردن(خط، ",")
هزینه := ستونها.بگیر(۱).به صحیح() * ستونها.بگیر(۲).به صحیح()
سرچاپ ستونها.بگیر(۰)، هزینه
جمع += هزینه
ستونها.آزادکن()
خط = ورودی خروجی.خواندن خط(پ)
پایان
سرچاپ "جمع کل:"، جمع
پایانیک نکته: خط خالیِ وسط پرونده هم به شکل رشتهی خالی برمیگردد و این حلقه همانجا میایستد. اگر پروندههای شما خط خالی دارند، جای خواندن را با اندازهی پرونده مقایسه کنید، یا اگر پرونده کوچک است با خط ها بخوانید. برای CSV واقعی با فیلدهای داخل گیومه، از encoding.csv استفاده کنید.
کدام تابع برای کدام کار
| کار | تابع |
|---|---|
| خواندن یکجای پروندهی کوچک | خواندن پرونده، یا خط ها برای وکتوری از خطها |
| بازنویسی پرونده | نوشتن پرونده، یا نوشتن خط ها از یک وکتور |
| افزودن به انتهای پرونده | افزودن به پرونده |
| خواندن پروندهی بزرگ بیآنکه همهاش بار شود | سیستم عامل.بازکردن، سپس خواندن یا خواندن خط، و در پایان بستن |
| رونوشت از یک پروندهی باز به پروندهی دیگر | کپی |
| گرفتن یک خط از کاربر | بخوان |
| گزارش خطا یا هشدار | نوشتن خطا و نوشتن خطا با خط جدید |
تابعها
بخوان Input
تابع بخوان(): رشتهورودی "" میکند. نمونهی زیر منتظر تایپ شماست، پس اینجا فقط ترجمه میشود و اجرا نمیشود.واردسازی ورودی خروجی
تابع ریشه:
چاپ "نام شما چیست؟ "
نام := ورودی خروجی.بخوان()
سرچاپ "خوش آمدی،", نام
پایانخواندن Read
تابع خواندن(f: پرونده*، size: طبیعی۶۴): رشتهsize بایت از جای فعلی پرونده میخواند. اگر به پایان پرونده رسیده باشید، رشتهی تهی برمیگرداند.واردسازی ورودی خروجی
واردسازی سیستم عامل
تابع ریشه:
ورودی خروجی.نوشتن پرونده("داده.txt"، "salam\ndonya\npayan\n")
پ := سیستم عامل.بازکردن("داده.txt"، "rb")
سرچاپ ورودی خروجی.خواندن خط(پ)
سرچاپ ورودی خروجی.خواندن(پ، ۳ برگردان طبیعی۶۴)
ورودی خروجی.جابجایی مکان نما(پ، ۰، ۰)
چاپ ورودی خروجی.خواندن همه(پ)
ورودی خروجی.بستن(پ)
پایانخواندن خط Readline
تابع خواندن خط(f: پرونده*): رشته\n آخرش (اگر پیش از آن \r باشد، میماند). در پایان پرونده رشتهی تهی برمیگرداند و برای خط خالی هم همین را؛ پس حلقهای که با "" میایستد، سر نخستین خط خالی هم میایستد.نمونهی این مورد همراه با موارد بالاتر آمده است: io-Read.salam
نوشتن Write
تابع نوشتن(f: پرونده*، data: رشته): صحیحپوچ باشد، منفی یک.واردسازی ورودی خروجی
واردسازی سیستم عامل
تابع ریشه:
پ := سیستم عامل.بازکردن("گزارش.txt"، "wb")
ن := ورودی خروجی.نوشتن(پ، "گزارش امروز\n")
ورودی خروجی.بستن(پ)
سرچاپ "بایتهای نوشتهشده:", ن
مبدأ := سیستم عامل.بازکردن("گزارش.txt"، "rb")
مقصد := سیستم عامل.بازکردن("رونوشت.txt"، "wb")
سرچاپ "رونوشت:", ورودی خروجی.کپی(مقصد، مبدأ), "بایت"
ورودی خروجی.بستن(مبدأ)
ورودی خروجی.بستن(مقصد)
چاپ ورودی خروجی.خواندن پرونده("رونوشت.txt")
پایانجابجایی مکان نما Seek
تابع جابجایی مکان نما(f: پرونده*، offset: صحیح۶۴، whence: صحیح): صحیحoffset فاصله بر حسب بایت است و whence میگوید از کجا شمرده شود: صفر یعنی از آغاز پرونده، یک یعنی از جای فعلی و دو یعنی از پایان پرونده. اگر موفق شود صفر و اگر نشود منفی یک برمیگرداند.نمونهی این مورد همراه با موارد بالاتر آمده است: io-Read.salam
بستن Close
تابع بستن(f: پرونده*)دیرکن است.نمونهی این مورد همراه با موارد بالاتر آمده است: io-Read.salam
خواندن پرونده ReadFile
تابع خواندن پرونده(path: رشته): رشتهواردسازی ورودی خروجی
تابع ریشه:
مسیر := "یادداشت.txt"
ورودی خروجی.نوشتن پرونده(مسیر، "خط نخست\n")
ورودی خروجی.افزودن به پرونده(مسیر، "خط دوم\n")
چاپ ورودی خروجی.خواندن پرونده(مسیر)
سرچاپ ورودی خروجی.خواندن پرونده("پروندهای که نیست.txt") == ""
پایاننوشتن پرونده WriteFile
تابع نوشتن پرونده(path: رشته، data: رشته): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: io-ReadFile.salam
افزودن به پرونده AppendFile
تابع افزودن به پرونده(path: رشته، data: رشته): صحیحنوشتن پرونده تعداد بایتها یا منفی یک برمیگرداند.نمونهی این مورد همراه با موارد بالاتر آمده است: io-ReadFile.salam
خط ها Lines
تابع خط ها(path: رشته): وکتور<رشته>آزادکن رها کنید.واردسازی ورودی خروجی
تابع ریشه:
ناپایا خطها := وکتور {} برگردان وکتور<رشته>
دیرکن خطها.آزادکن()
خطها.بیفزا("سیب")
خطها.بیفزا("انار")
خطها.بیفزا("انگور")
بایت := ورودی خروجی.نوشتن خط ها("میوهها.txt"، خطها)
سرچاپ "نوشته شد:", بایت, "بایت"
خوانده := ورودی خروجی.خط ها("میوهها.txt")
دیرکن خوانده.آزادکن()
هر ش، م در خوانده:
سرچاپ ش + ۱, م
پایان
پایاننوشتن خطا EPrint
تابع نوشتن خطا(s: رشته)واردسازی ورودی خروجی
تابع ریشه:
سرچاپ "این در خروجی عادی است"
ورودی خروجی.نوشتن خطا("هشدار: ")
ورودی خروجی.نوشتن خطا با خط جدید("این پیام در خروجی خطا میرود")
چاپ "بدون خط تازه..."
ورودی خروجی.تخلیه()
سرچاپ ""
پایاننوشتن خطا با خط جدید EPrintln
تابع نوشتن خطا با خط جدید(s: رشته)نوشتن خطا، ولی پس از پیام به خط بعد میرود.نمونهی این مورد همراه با موارد بالاتر آمده است: io-EPrint.salam
تخلیه Flush
تابع تخلیه()چاپ متنی بدون پایان خط نوشتهاید و میخواهید کاربر فوراً آن را ببیند، به کار میآید.نمونهی این مورد همراه با موارد بالاتر آمده است: io-EPrint.salam
خواندن همه ReadAll
تابع خواندن همه(f: پرونده*): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: io-Read.salam
کپی Copy
تابع کپی(dst: پرونده*، src: پرونده*): صحیح۶۴src مانده را در پروندهی dst مینویسد و تعداد بایتهای رونوشتشده را برمیگرداند. برای پروندههای بزرگ مناسب است، چون همهی پرونده را یکجا در حافظه نمیآورد.نمونهی این مورد همراه با موارد بالاتر آمده است: io-Write.salam
نوشتن خط ها WriteLines
تابع نوشتن خط ها(path: رشته، lines: وکتور<رشته>): صحیحنمونهی این مورد همراه با موارد بالاتر آمده است: io-Lines.salam