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

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

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

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

std::filesystem مجموعه‌ی کاملی از توابع را برای انجام عملیات‌های رایج ارائه می‌دهد . تابع exists بررسی می‌کند که آیا یک مسیر معتبر وجود دارد یا خیر و create_directory امکان ساخت یک دایرکتوری جدید را فراهم می‌کند. عملیات کپی، جابه‌جایی و حذف فایل‌ها و دایرکتوری‌ها از طریق توابع copy، rename و remove انجام می‌شود . برای بررسی نوع یک فایل می‌توان از is_directory و is_regular_file استفاده کرد و file_size اندازه‌ی فایل را بازمی‌گرداند. همچنین امکان دریافت مسیر مطلق (absolute) و مسیر متعارف (canonical) که شامل هیچ‌گونه پیوند سمبلیک یا عناصر . و .. نیست، وجود دارد .

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

یکی از پرکاربردترین قابلیت‌های این کتابخانه، پیمایش دایرکتوری‌هاست. با استفاده از directory_iterator می‌توان به‌سادگی تمام ورودی‌های یک دایرکتوری را لیست کرد . این کلاس از حلقه‌های مبتنی بر محدوده (Range-based for loops) پشتیبانی می‌کند و کدنویسی را بسیار ساده می‌سازد . برای پیمایش بازگشتی تمام زیرشاخه‌ها نیز recursive_directory_iterator در دسترس است . هر دو کلاس به‌گونه‌ای طراحی شده‌اند که استفاده از آنها با حلقه‌های for مدرن، شهودی و بدون نیاز به مدیریت دستی تکرارگرها باشد . کلاس directory_entry نیز اطلاعات کاملی درباره‌ی هر ورودی، از جمله مسیر و وضعیت فایل، در اختیار برنامه‌نویس قرار می‌دهد .

مدیریت خطا و ملاحظات مهم

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

کلیدواژه ها : std::filesystem-کتابخانه فایل سیستم در C++17-عملیات کراس پلتفرم فایل-C++17 filesystem tutorial-پیمایش دایرکتوری در C++-std::filesystem path-ایجاد دایرکتوری در C++-std::filesystem directory_iterator-std::filesystem recursive_directory_iterator-مدیریت فایل در C++-توابع filesystem C++-مقایسه boost.filesystem و std::filesystem-std::filesystem exists-std::filesystem copy-std::filesystem remove-آموزش std::filesystem-کاربرد std::filesystem