Haftalık C++ 6 – Dosya Sistemi Kütüphanesi

Herkese merhabalar, bir aradan sonra (umarım çok da uzun olmayan), yeni bir haftalık C++ yazımız ile birlikteyiz. Bu yazımda, sizler ile birlikte uzun bir süre beklenen (aslında Java ve .Net gibi bir çok platform ile sunulan ama C++ da standart bir şekilde sunulmayan) STL kabiliyeti olan, dosya sistemi kütüphanesine bir göz atacağız.

Bu kütüphane, aslında uzunca bir süredir (yaklaşık 2003) kullanılmakta olan boost::filesystem kütüphanesini baz alıyor diyebiliriz. O kütüphane de oldukça yaygın ve birçok kişi tarafından kullanılıyor, ayrıca merak edenler için de 😉 boost ve standart dosya sistemi kütüphanelerini karşılaştıran bir bağlantı veriyorum. Elbette standart dosya sistemi kütüphanesinin en önemli amacı sizin de tahmin edebileceğiniz üzere bir çok platform için standart kod yazabilmek. Bu yazımda da, kütüphanenin öne çıkan özellikleri üzerinden geçip, bunları örnek kullanımlarla sizlere aktarmaya çalışacağım. Bunun ile birlikte daha detaylı bilgi edinmek için de sizlere ilgili kaynakları sunacağım. Bu arada eğer fırsat bulabilirsem, hazırlayacağım bazı haftalık C++ yazılarında bu kütüphanenin örnek kullanımlarını verebilirim.

Giriş:

Stackoverflow yazısında ifade edildiği üzere, bu kütüphaneye yapılan değişikliklere ilişkin bir çok yayın mevcut. Bunlara aşağıdaki bağlantılardan ulaşabilirsiniz:

  • P0219R1, göreceli yol desteği eklenmesi,
  • P0317R1, directory_entry’ye ön bellek (cache) eklenmesi,
  • P0492R2, gelen görüşler ışığında yapılan bir çok hata ve güncellemeler,
  • P0430R2, bazı Non-POSIX sistemler için destek,
  • P0218R1, nihai yayın.

Kütüphaneye dair güncellemeleri “LWG issue list” listesinden takip edebilirsiniz. Ayrıca C++ standardının diğer parçalarına/kabiliyetlere dair hususları da buradan takip edebilirsiniz.

Ayrıca C++ standart dokümanı içerisindeki 30.10 başlığından da dosya sistemine dair detaylara ulaşabilirsiniz. Fakat dokümanın, oldukça büyük olduğunu ifade etmeliyim 🙂

Yukarıda da bahsettiğim üzere, kütüphane boost::filesystem’e dayanıyor ve kütüphane tarafından sunulan bazı bileşenler de opsiyonel. Bir diğer deyişle her platform ya da derleyici ile kullanılmayabilir (ör. sembolik kısayollar FAT-32 de desteklenmemektedir). Bunların yanında, aşağıda bazı platform (işletim sistemi) ile ilintili hususları da göz önüne almanızda fayda var:

  • Dosya karakter duyarlılığı. Ör. “file.txt”, “File.txt” ve “filet.TXT” her ne kadar Windows tabanlı işletim sistemlerinde aynı dosyaya karşılık gelse de Linux gibi POSIX tabanlı işletim sistemlerinde ise üç farklı dosyaya karşılık gelmektedir,
  • Göreceli/tam dosya yolu yaklaşımları. POSIX benzeri sistemlerde “/bin” dizini tam dosya dizinine karşılık gelse de, Windows tabanlı işletim sistemlerinde böyle bir yaklaşım hiç bulunmamaktadır,

Kütüphanedeki en önemli kavram dosya/dizin yolu (“path”). Bu aslında herhangi bir dosyanın (aynı zamanda dizinin) konumunu ifade eden etiket olarak nitelendirebiliriz. Tabi bu sadece dosya değil, aynı zamanda dizin, kısa yol, katı bağlantı ya da sembolik bağlantıları da ifade edebilir. Yol kavramının bu anlamda ifade edebileceği bütün değerleri görmek için dosya sistemi kütüphanesi sayfasına bakabilirsiniz. Bu yollar göreceli ya da bütün yolu ifade edebilir. Bazı platformların jenerik ya da kendilerine özel yol formatları da olabiliyor. Ör, Windows üzerinde “/tmp/test.txt” geçerli bir format olarak kabul ediliyor, “\tmp\test.txt” yolu da destekleniyor. Bu ikisi aynı yolu ifade eden platforma özgü gösterimler. Bu tarz gösterimler, platformlardan platforma değişebilmekte. Kütüphane bu tarz platform bağımlı dosya yolu ile daha jenerik gösterimler arasında dönüşüm için de API sunmakta.

Bu doğrultuda bakacak olursak genel yol formatı aşağıdaki gibi özetlenebilir:

The generic path format can be summarized as:
            [rootname] [rootdir] [relativepath]
where:

  • Burada opsiyonel olan kök ismi (“rootname”), platforma özgüdür (ör. POSIX sistemlerde “//host”, Windows tabanlı sistemlerde “C:” olabilmektedir.),
  • Bir diğer opsiyonel öğe kök dizini de dizin ayıracı olarak kullanılıyor,
  • Son olarak göreceli yol ise dosya ve dizin isimlerini içeren kısımdır.

Sizin de tahmin edebileceğiniz üzere dosya sistemi kütüphanesi oldukça büyük bir kütüphane ve bütün detaylarını bir yazıda vermek oldukça zor. Burada olabildiğince önemli olan kabiliyetlerin üzerinde durup, daha çok pratik kullanım alanı olan özelliklerini örnek kodlar ile vermeye çalışacağım. Daha fazla detay öğrenmek isterseniz, sizlere kaynaklar kısmındaki Nicolai. M. Jouttis ve diğer C++ 17 kitaplarını önerebilirim.

Dosya sistemi kütüphanesini kullanmak için <filesystem> başlık dosyasını eklemeli ve filesystem:: alanını kullanmalısınız. Kütüphane içerisinde hem sınıflar hem de bağımsız metot şeklinde API’ler bulunmakta. Varsayılan olarak, kütüphane hataları istisna mekanizması (filesystem_error istisna nesnesi) ile kotarıyor (diğer kütüphanelere göre doğası gereği bu tarz durumların çok olabileceğini tahmin edersiniz diye düşünüyorum). İstisna mekanizması yanında isterseniz, ilgili hata kodlarını da parametre olarak dönen API’leri kullanabilirsiniz (std::error_code).

İlgili alan uzayı ve başlık dosyası derleyici ve IDE’nize göre değişiklik gösterebilir, bu konuya son başlıkta (derleyici desteği) değineceğim.

Bu kadar açıklama yeter sanırım, hemen bir örnek ile kütüphaneyi kullanmaya başlayalım:

Yukarıda görebileceğiniz üzere dizin işlemlerini sunulan bu API’ler ile kolay bir şekilde gerçekleştirebilirsiniz. Peki daha başka neler yapabiliriz:

  • Dizin oluşturma/içeriğini izleme,
  • Dizin düzenlemeleri ve karşılaştırma,
  • Dizin isimlerinin platform özgü ve jenerik dönüşümleri
  • Dizin ve dosyalar arasında dolaşma,
  • Dosya niteliklerini, durumunu ve yetkileri izleme/değiştirme,
  • Dosya işlemleri (oluşturma, silme, kopyalama, taşıma),
  • Çok daha fazlası için https://en.cppreference.com/w/cpp/filesystem sayfasına bir göz atabilirsiniz

Yol Nesneleri:

Şimdi en çok kullanılan nesnelerden birisi olan yol nesnelerine göz atalım. Aslında bakarsanız aşağıdaki örnek bu sınıfa ilişkin çoğu örnek kullanımı göstermekte. Bunların bir çoğu günlük kullanımda ihtiyaç duyabileceğiniz kabiliyetler. Hemen bakalım.

Boş Disk Alanı Bilgisi:

Bir diğer kullanışlı sınıf ise std::filesystem::space_info. Bu sınıf sayesinde dosya sistemine ilişkin boş ve kullanılabilir alan bilgileri aşağıda gösterildiği şekilde sorgulanabilir:

İzinler:

Aşağıda gösterildiği şekilde dosyaların izin nitelikleri ile de oynayabilirsiniz. Bu anlamda BitmaskTypetipinde olan std::filesystem::perms maskeleri kullanılmakta (detaylar için https://en.cppreference.com/w/cpp/filesystem/perms)’a göz atabilirsiniz). Aşağıda ilgili izinleri nasıl görüntüleyip, değiştirebileceğinizi bulabilirsiniz:

Son Düzenleme Zamanı:

Bu kütüphane ve std::chrono kütüphanesini de kullanarak herhangi bir dosyanın son düzenlenme tarihini görebilirsiniz. Aşağıdaki örnek kod, bu kullanımı göstermekte:

Derleyici/Kütüphane Desteği:

Kullandığınız derleyicinin bu kabiliyeti destekleyip desteklemediğini, diğer kabiliyetler ile birlikte https://en.cppreference.com/w/cpp/compiler_support adresinden kontrol edebilirsiniz.
Derleyicinizin sürümüne göre std::experimental::filesystem isim alanı kullanmanız gerekebilir.

GCC: “-lstdc++fs” opsyionu eklenmelidir. Ayrıca “<experimental/filesystem>” başlığını eklemeniz gerekiyor.
Clang: Clang 5.0 ile destek sunuluyor. https://libcxx.llvm.org/cxx1z_status.html
Visual Studio: Visual studio 2017 için ise <filesystem> başlığını ekleyip, std::experimental::filesystem isim alanını kullanmalısınız (yukarıdaki örnekler de bu şekilde).

Kaynaklar:

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.

This site uses Akismet to reduce spam. Learn how your comment data is processed.