پیش از C++17، کار با فایل‌ها و دایرکتوری‌ها در C++ یکی از چالش‌برانگیزترین بخش‌های برنامه‌نویسی بود. برنامه‌نویسان مجبور بودند برای هر سیستمعاملی از توابع جداگانه استفاده کنند؛ برای مثال، در لینوکس از opendir() و readdir() و در ویندوز از FindFirstFile() و FindNextFile() بهره می‌بردند . C++17 با معرفی کتابخانه‌ی std::filesystem در هدر <filesystem>، راه‌حلی یکپارچه و کراس‌پلتفرم برای این نیاز اساسی ارائه کرده است که با یک کد واحد می‌توان در سیستمعامل‌های مختلف مانند لینوکس، مک‌اواس و ویندوز، عملیات فایل‌سیستم را انجام داد .

ساختار و مؤلفه‌های اصلی

تمامی شناسه‌های این کتابخانه در فضای نام std::filesystem تعریف شده‌اند . هسته‌ی این کتابخانه، کلاس path است که نشان‌دهنده‌ی مسیر یک فایل یا دایرکتوری می‌باشد و یک نمایش قابل‌حمل از مسیرها ارائه می‌دهد. علاوه بر path، کلاس‌های مهم دیگری نیز در این کتابخانه وجود دارند، از جمله directory_iterator برای پیمایش محتویات یک دایرکتوری، recursive_directory_iterator برای پیمایش زیرشاخه‌ها به‌صورت بازگشتی، و filesystem_error برای مدیریت خطاهای مربوط به عملیات فایل‌سیستم .

عملیات‌های کلیدی بر روی فایل‌ها و دایرکتوری‌ها

کپی کردن فایل‌ها

برای کپی کردن فایل‌ها، کتابخانه دو روش اصلی ارائه می‌دهد: تابع عمومی copy و تابع تخصصی‌تر copy_file . هنگام کپی فایل‌ها، تعیین سیاست برخورد با نام‌های تکراری از اهمیت ویژه‌ای برخوردار است. برای مثال، استفاده از copy_options::overwrite_existing明確اً مشخص می‌کند که فایل مقصد در صورت وجود، بازنویسی شود، در حالی که copy_options::skip_existing از بازنویسی جلوگیری می‌کند .

تغییر نام و جابه‌جایی

تابع rename نه تنها برای تغییر نام یک فایل، بلکه برای جابه‌جایی آن بین مسیرهای مختلف نیز کاربرد دارد . این عملیات در سیستم‌های مختلف، نوعی «تغییر نشانه» (جدول مسیر) است و داده‌ها را کپی نمی‌کند. یک کاربرد کلاسیک آن، چرخش لاگ‌ها (log rotation) است که در آن فایل لاگ فعلی به نسخه‌ی قدیمی‌تر تغییر نام می‌یابد .

حذف فایل‌ها و دایرکتوری‌ها

تابع remove برای حذف یک فایل یا یک دایرکتوری خالی به کار می‌رود . مقدار بازگشتی bool این تابع نشان‌دهنده‌ی این است که آیا چیزی واقعاً حذف شده است یا خیر؛ برای مثال، اگر فایل از قبل وجود نداشته باشد، مقدار false بازمی‌گردد که به‌معنای وقوع خطا نیست، بلکه به‌معنای «چیزی برای حذف کردن وجود نداشت» است . برای حذف کامل یک دایرکتوری و تمام محتویات آن، از remove_all استفاده می‌شود .

پیمایش دایرکتوری‌ها

directory_iterator

با استفاده از directory_iterator می‌توان به‌سادگی تمام ورودی‌های یک دایرکتوری را لیست کرد . این کلاس از حلقه‌های مبتنی بر محدوده (Range-based for loops) پشتیبانی می‌کند و کدنویسی را بسیار ساده می‌سازد .

recursive_directory_iterator

برای پیمایش بازگشتی تمام زیرشاخه‌ها، recursive_directory_iterator در دسترس است . یکی از قابلیت‌های مفید این کلاس، متد depth() است که عمق جاری در سلسله‌مراتب دایرکتوری‌ها را بازمی‌گرداند؛ دایرکتوری شروع با عمق ۰ و زیرشاخه‌های آن با عمق ۱ و به‌همین ترتیب مشخص می‌شوند . همچنین متدهای begin و end این امکان را فراهم می‌کنند که از این تکرارگرها به‌طور مستقیم در حلقه‌های for استفاده شود .

کلاس path و عملیات روی مسیرها

کلاس path امکانات متنوعی برای کار با اجزای مسیر ارائه می‌دهد. با متد filename() می‌توان بخش نام فایل را از یک مسیر استخراج کرد و با replace_extension() می‌توان پسوند فایل را تغییر داد . عملگر / امکان اتصال دو مسیر را با افزودن جداکننده‌ی مناسب فراهم می‌آورد و یک روش قابل‌حمل برای ساخت مسیرهای جدید است .

مدیریت خطا و دوگانگی توابع

تقریباً تمام توابع این کتابخانه در دو نسخه وجود دارند: نسخه‌ای که در صورت بروز خطا، استثنای std::filesystem::filesystem_error پرتاب می‌کند و نسخه‌ای که یک شیء error_code را به‌عنوان پارامتر دریافت کرده و خطا را از طریق آن گزارش می‌دهد . این طراحی به برنامه‌نویس این امکان را می‌دهد که بر اساس نیاز خود، بین مدیریت خطا با استثنا یا بررسی کد خطا، یکی را انتخاب کند .

کلیدواژه ها : std::filesystem-کتابخانه فایل سیستم در C++17-عملیات کراس پلتفرم فایل-پیمایش دایرکتوری در C++-std::filesystem path-ایجاد دایرکتوری در C++-directory_iterator-recursive_directory_iterator-مدیریت فایل در C++-کپی فایل در C++-rename در C++-remove و remove_all-std::filesystem depth-مدیریت خطا در filesystem-std::filesystem_error-آموزش std::filesystem-کاربرد std::filesystem