22 Ağustos 2017 Salı

Dizin İşlemleri

Bu yazıyla ilgili olarak Dosya İşlemleri başlıklı yazıya göz atabilirsiniz. 
Dizin Kopyalama
Apache Commons
FileUtils Sınıfı copyDirectory metodu yazısına taşıdım.

Dizin Silme
C 
rmdir(const char* path) metodu ile sadece boş olan bir dizin silinebilir. Dizin boş değilse hata kodu atanır.
If the directory is not an empty directory, rmdir() shall fail and set errno to [EEXIST] or [ENOTEMPTY]..

boost
boost::filesystem::remove_all() metodu ile verilen dizin ve altındaki diğer dizin ve dosyalar silinirler.
Eğer verilen dizin değil de sadece içi silinsin isteniyorsa aşağıdaki gibi yapılabilir.
Örnek:
namespace fs=boost::filesystem;
fs::path path_to_remove("C:\\DirectoryToRemove");
for(fs::directory_iterator end_dir_it, it(path_to_remove); it!=end_dir_it; ++it) {
  remove_all(it->path());
}
Eğer dizin veya dosya silinemezse bir exception atılır. Bu exception yakalanarak tekrar denemek için aşağıdaki kod kullanılabilir.
 
C#
Directory.Delete (path,true); metodu ile verilen dizin ve altındaki diğer dizin ve dosyalar silinirler

Windows
Shell API kullanılırsa SHFileOperation ile silinebilir. Kullanılmazsa buradaki kod kullanılabilir.

Dizinin Yaratma
C 
#include < sys/stat:h >
if
(mkdir(location.c_str(), S_IRWXU) != 0){
    //hata
}
S_IRWXU read, write, execute by user (owner) anlamına geliyor.
boost

Eğer dizinler iç içe açılacaksa aşağıdaki gibi yapılabilir.

boost::filesystem::create_directories( "c:\\foo\\bar" );
Java
Eğer tek bir dizin açılacaksa File.mkdir() kullanılır. Eğer iç içe dizinler açılacaksa File.mkdirs() kullanılır. Örnek:
File  f = new File("non_existing_dir/someDir");
f.mkdirs()
Windows
if (!CreateDirectory(location.c_str(), NULL) &&
    ERROR_ALREADY_EXISTS != GetLastError())
{
    err << GetLastError();
}
Gizli Dizinin Yaratma
C
Bu iş Unix üzerinde dosya isminin başına . işareti getirilerek yapılıyor. Örnek:

Geçici Dizini Bulma
Çoğu mobil cihazda geçici dizin kavramı yoktur.
C#
Path.GetTempPath() ile geçici dizin bulunabilir. Çağrı sonucunda şuna benzer bir çıktı alırız.
"%USERPROFILE%AppData\Local\Temp"
Geçici Dizin Oluşturma
C
mkdtemp ile geçici dosya oluşturuluyor.

Dizinin Varlığını Kontrol Etme
C
stat  metodu ile dizinin varlığı kontrol edilebilir. Örnek:
if(stat(location.c_str(), &st) != 0){
    //dizin yok
}
boost
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>

namespace fs = boost::filesystem;
fs::path somedirectory ("some path");
fs::is_directory(somedirectory);
Bir başka örnek ise
fs::file_status folderStatus =  fs::status("some path");
fs::is_directory(folderStatus) ;  
Dizinin Altını Dolaşma

Dizin İşlemleri - Dizini Dolaşma başlıklı yazıya taşıdım.

Dizinin Büyüklüğünü Bulma
POSIX
Örneği buradan aldım.

int total_size = 0; // Global, to accumulate the size
void* dirsize(void* dir)
{
    DIR* dp=opendir("dirpath");
    // Loop over files in directory
    while ((entry = readdir(dp)) != NULL)
    {
        ...

        // Check if directory
        if (S_ISDIR(statbuf.st_mode))
        {
            dirsize (strcpy (entry->d_name));
        }
        else
        {
            // Add filesize
            total_size += statbuf.st_size;
        }
    }
    closedir(dirp);
}

Özel Dizinler
Özel Dizin İşlemleri yazısına taşıdım.

Exe'nin Bulunduğu Dizini Alma
Tüm işletim sistemlerine mahsus çözümler burada
argv [0] değerini okumak her zaman exe'nin bulunduğu dizini bulmamızı sağlamaz!

Linux
readlink() metodunu kullanarak sembolik link olan /proc/sef/exe okunarak yapılabilir. procfs hakkında bilgi almak için procfs ve tmpfs başlıklı yazıya göz atabilirsiniz.

Örnek:
Bir başka örnek:
char szTmp[32];
sprintf(szTmp, "/proc/%d/exe", getpid());
readlink(szTmp, pBuf, len);
Windows
GetModuleFileName ile yapılıyor.
Örnek
Genel kod için şöyle yaparız.

TCHAR dest[MAX_PATH];
GetThisPath(dest, MAX_PATH);
Örnek
Unicode derlerken şöyle yaparız.

#include <windows.h>
...
WCHAR dirname[1024];
GetModuleFileNameW(NULL, dirname, 1024);
Örnek:
#include <windows.h>
char ownPth[MAX_PATH];
GetModuleFileName(NULL, pBuf, MAX_PATH);
C#
Application.CurrrentDomain.BaseDirectory ile alınabilir.
Application.StartupPath ile de alınabilir.
System.IO.Path.Combine(Application.StartupPath, @"Resources\check_active.png");


Çalışılan Dizini Alma
C  
char *getcwd(char *buf, size_t size); ile programın çalıştığı dizin alınabilir. Örnek:
char* initial_cur_dir = malloc(1000);
getcwd(initial_cur_dir, 1000);
Bu metodun açıklamasında kullanılan şu cümle önemli. Metodun aynı zamanda I/O yapılan dizini gösterdiği de anlatılmış.
This method shall get the default I/O path.

boost
Burada açıklandığı gibi current_path ile şimdiki dizin alınabilir.

QT
QCoreApplication::applicationDirPath() ile programın çalıştığı dizin alınabilir.

C#
Directory.GetCurrentDirectory ile alınabilir.

Çalışılan Dizini Değiştirme
C#
Directory.SetCurrentDirectory metodu ile yapılabilir.

Verilen Dizinin Yolunu Native Olarak Alma
QT
 QDir::fromNativeSeparators ile Windows dizinler Unix tarzına dönüştürülebilir. Örneğin 
QString myUnixPath = QDir::fromNativeSeparators("c:\\winnt\\system32");//c:/winnt/system32
Verilen Göreceli Dizini Tam Dizin Yoluna Çevirme
boost
system_complete ile göreceli olan dizin, tam dizin yoluna çevirilir. Örnek:

Native Dizin Ayracını Alma
QT
QDir::separator() ile alınabilir.
Java
File.sepatator ile alınabilir.

Dizinleri Ekleme
C
Basit bir strcat kullanılabilir. Ancak bu metod buffer overflow hatasına biraz müsait.
ConcatPath(char *fullpath, char *subdir, char *filename)
{
    strcat(fullpath, BASE_PATH);  
    strcat(fullpath, subdir); 
    strcat(fullpath, "/");
    strcat(fullpath, filename);
}

snprintf daha makul bir çözüm
bool build_path(char *dest, size_t size, char *subdir, char *filename)
{
    // Don't assume the input is valid
    if ( (dest == NULL) || (size < 1) || (filename == NULL) ) {
        return false;
    }

    // Make no subdir work  (sane default behavior)
    if ( subdir == NULL ) {
        subdir = "";
    }

    // Prevent buffer overruns by using a safe formatting function
    size_t stored = snprintf(dest, size, BASE_PATH "/%s/%s", subdir, filename);

    // Returns success (true) if the path fit the buffer
    return ((stored+1) <= size);
}


QT
QT ile aşağıdaki kod kullanılabilir. Fonksiyona girdi olan path1, path2 parametreleri teker teker temizlenmiyor. Her birisi "/" ile bitse bile ekleme işlemi sonunda QDir::cleanPath() metodu ile sonuç temizleniyor.
QString appendPath(const QString& path1, const QString& path2)
{
    return QDir::cleanPath(path1 + QDir::separator() + path2);
}
Java
Java 7 ile Paths.get kullanılabilir.

C#
IO.Path.Combine ile dizinler eklenebilir.
var basePath = @"\\server\BaseFolder";
var relativePath = @"\My\Relative\Folder";

var combinedPath = Path.Combine(basePath, relativePath);
Not : Combine metoduna verilen ikinci parametre, yan relative path "\" karakteri ile başlamamalıdır! Başlarsa absolute path olur ve istediğimiz sonucu alamayız.

Daha da ilkel bir yöntem Path.DirectorySeparatorChar kullanarak kendi kendimize eklememiz.
string sound = Application.ExecutablePath + string.Format ("{0}Sounds{0}Finished.wav", Path.DirectorySeparatorChar);

Diskleri Dolaşma
Java
File.listRoots() ile bu iş yapılabiliyor. Örneği buradan aldım.

Böylece C:\\ ile başlayan sabit bir dizin yerine File.listRoots()[0] kullanılabilir.

Diskin Mantıksal Block Büyüklüğünü Bulma
C
Buradaki soruda bu iş için standart bir metod bulunmadığı ancak Linux'ta ioctl, Solaris'te dkio, Windows'ta ise DeviceIoControl kullanılarak yapılabileceği söylenmiş. Örnek:
ioctl(fd, BLKPBSZGET, &block_size);


Hiç yorum yok:

Yorum Gönder