На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела FAQ в группе разделов С++.
1. Раздел FAQ предназначен для публикации готовых статей.
2. Здесь нельзя задавать вопросы, для этого существуют соответствующие разделы:
Чистый С++
Visual C++ / MFC / WTL / WinApi
Borland C++ Builder
COM / DCOM / ActiveX / ATL
Сопутствующие вопросы
3. Внимание, все темы и сообщения в разделе премодерируются. Любое сообщение или тема будут видны остальным участникам только после одобрения модератора.
Модераторы: B.V., Qraizer
  
> Создание директории
    Очень часто в форуме возникают вопросы про создание директорий.
    Штука достаточно простая, большинство бы и так догадалось как делать, но иногда нужно просто держать сухим нужный кусок кода, вынуть его из заначки и применить.

    Расскажу – как нужно делать.
    Нужно воспользоваться API-шной функцией CreateDirectory. Функция – повторюсь, из WinAPI, в MFC ничего подобного нет. Несколько раз видел в ответ на скупой и лаконичный ответ “CreateDirectory” вопрос “Это у какого класса такой метод?”. Вопрос подобный повергает меня в смущение, но это уже оффтопик.

    А теперь рассмотрим очень часто встречающуюся ситуацию, когда при создании директории “C:\\1\\2\\3\\4” в момент попытки создания не существует ни директории 1, ни 2, ни 3, ни 4. В общем – создать её в этом случае одним вызовом CreateDirectory() не удастся.
    Тогда можно воспользоваться обещаным куском кода.

    Данный код не привязан к Visual C++ или, например, lcc (на котором он и был написан), и вообще к С++ (на Дельфи ситуация будет выглядеть очень похоже, сдецл поменияется только синтаксис).

    ExpandedWrap disabled
       
       
      TCHAR   sPathTo [] = “c:\\1\\2\\3\\4\\5\\6\\7\\8”;//директория, которую нужно создать
       
      bool AQLCreateDirectory(TCHAR * sPathTo)
      {
        //пока директория не создана, будем пытаться её создать//
        while(CreateDirectory(sPathTo, NULL) == FALSE)
        {
          /* директория не создана, поэтому нужно сначала создать ”предыдущую” директорию */
          TCHAR   sTemp[MAX_PATH];
          int k = strlen(sPathTo);
          strcpy(sTemp, sPathTo);
       
          //пытаемся найти и создать директорию самого “нижнего” уровня
          while(CreateDirectory(sTemp, NULL) != TRUE)
          {
            /* пытаемся найти первичные половые признаки предыдущей директории.... */
            while(szTemp1[--k] != '\\')            
            {
              if(k<=1)                        
                return FALSE;/* похоже, что директория создана быть вообще не может!
              sTemp[k] = NULL;
            }
            /* ......а как только нашли - создать её */    
          }
          //во время первого прохода будет создана директория “1”, во время второго – “2” и т.д.
        }
        return TRUE;
      }


    В общем, код достаточно простой, и ясен почти без комментариев.
    Более того: его можно изменить. Например: разобрать один раз строку с исходным путём, и потом создать подряд все директории, начиная с первой (может уменьшиться время потраченое на разбор строки), но могу сказать, почему я этого не сделал. Если не хватает 1-ой 2-х директорий в самом конце пути (наиболее часто встречающаяся ситуация), то код будет работать не намного дольше, а может и вообще быстрее (если вложенность большая).

    Причин, по которым директория не может быть создана может быть много, например - у пользователя не хватает прав. В этом случае код можно расширять и дополнять.
      Цитата AQL @ 29.02.04, 14:25
      Несколько раз видел в ответ на скупой и лаконичный ответ “CreateDirectory” вопрос “Это у какого класса такой метод?”. Вопрос подобный повергает меня в смущение, но это уже оффтопик.

      Странно, неужели и так нельзя понять, что это API функция. Мне б и ничего другого в голову не пришло при прочтении такого ответа, кроме как то, что это API.
      Функция конечно нужная, но, помоему, человек, которому она могла понадобиться и сам бы написал ее :huh:
      А в Delphi, помоему такая функция реализована... Я точно не знаю, но уже видел топик с такой темой, и там человек, которому эта ф-я понадобилась писал, что в Delphi она есть. <_<

      А вообще эту тему можно добавить в ФАК, помоему -достойна. :angry:
        Функция стопудово нужная. А то, что функция API-шная доходит далеко не сразу и далеко не до всех.
        (кстати - в Дельфях она кажись и вправду уже есть, но у нас то С++, все делаем ручками).
        Сообщение отредактировано: AQL -
          Цитата
          AQL, 29.02.04, 18:47
          кстати - в Дельфях она кажись и вправду уже есть

          Ага: function ForceDirectories(const Dir: string): Boolean;
          ЗЫ. Я в принципе согласен с kipelov, "любой" человек напишет эту функцию, если ему она понадобится, но человек щас ленивый пошёл, так что думаю она будет востребованна... ^_^
            В приведенной функции есть недочет - она не создаст директорию "C:/Temp/1/2/3", хотя в принципе такой формат задания имени допустИм.
              Да AQL, я согласен с Дядей...и он там был не один ;)
              Я те тут подправил....
              ExpandedWrap disabled
                 
                BOOL AQLCreateDirectory( LPCTSTR sPathTo)
                {
                    BOOL bRet = sPathTo ? TRUE : FALSE;
                    //пока директория не создана, будем пытаться её создать
                    while( bRet && (bRet = CreateDirectory(sPathTo, NULL)) == FALSE)
                    {
                        // директория не создана, поэтому нужно сначала создать ”предыдущую” директорию
                        __try {
                        int k = lstrlen( sPathTo);
                        if( k >= MAX_PATH) break; // Слишком длинное имя....
                        LPTSTR   sTemp = LPTSTR( _alloca( (k + 1) * sizeof(TCHAR))); // Экономия стека :)
                        lstrcpy( sTemp, sPathTo);
                        while( k && sTemp[ k] != TCHAR('\\') && sTemp[ k] != TCHAR('/')) --k;
                        if( k <= 0) break; // похоже, что директория создана быть вообще не может!
                        sTemp[ k] = TCHAR( '\0');
                        bRet = AQLCreateDirectory( sTemp);
                        } __except( GetExceptionCode() == STATUS_STACK_OVERFLOW) { break; }
                    }
                    return bRet;
                }


              Тестировал:
              ExpandedWrap disabled
                 
                int _tmain(int argc, _TCHAR* argv[])
                {
                    BOOL bRet;
                    bRet = AQLCreateDirectory( NULL);                   // Error creating
                    bRet = AQLCreateDirectory( "\\");                   // Error creating
                    bRet = AQLCreateDirectory( "");                     // Error creating
                    bRet = AQLCreateDirectory( "C:\\");                 // Error creating
                    bRet = AQLCreateDirectory( ":");                    // Error creating
                    bRet = AQLCreateDirectory( "1");                    // Succesfull
                    bRet = AQLCreateDirectory( "1\\2\\3\\4\\5\\6");     // Succesfull
                    bRet = AQLCreateDirectory( "\\1\\2\\3\\4\\5\\6");   // Succesfull
                    bRet = AQLCreateDirectory( "C:\\1\\2\\3\\4\\5\\6"); // Succesfull
                    bRet = AQLCreateDirectory( "C:/1/2/3/4/5/6");       // Succesfull
                 
                    return 0;
                }

              Мож кто-то ещё чего натестит....
              Сообщение отредактировано: AlexSm -
                2Lucifer>> MSDN about MakeSureDirectoryPathExists:
                Цитата

                Requirements
                Client: Included in Windows XP and Windows 2000 Professional.
                  В UNIX-like директория создается вызовом
                  Цитата

                  int mkdir(const char *pathname, mode_t mode);

                  mode - права доступа.

                  Просмотр директории
                  Цитата

                  #include <sys/types.h>
                  #include <dirent.h>

                  char * path = "path";

                  DIR *dir = opendir(path);
                  dirent *dirp;

                  while ( (dirp = readdir(dir)) != NULL ) {
                  // Печать всех содержащихся в path файлов и директорий
                  printf ("%s\n", dirp->d_name);
                  }

                  closedir (dir);
                  Сообщение отредактировано: lunc -
                    Спасибо за дополнения ;)
                    (про рекурсии - не люблю я их, поэтому и не использовал).
                    Сообщение отредактировано: AQL -
                      Поиск путей по шаблону (для UNIX-like)

                      man glob

                      Например для поиска файлов типа "../*.[c,h]":

                      ExpandedWrap disabled
                         
                        #include <glob.h>
                         
                        glob_t globbuf;
                         
                        if ( !!glob("../*.[c,h]", 0, NULL, &globbuf) ) { // Ищем
                           printf ("ERROR\n");
                           return -1;
                        }
                         
                        for (int i = 0; i < globbuf.gl_pathc; i++) {  // Читаем все пути
                           printf ("\t%s\n", globbuf.gl_pathv[i]);    // Выводим
                        }


                      Вывод будет аналогичным выводу ls ../*.[c,h]
                      Сообщение отредактировано: lunc -
                      1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                      0 пользователей:


                      Рейтинг@Mail.ru
                      [ Script execution time: 0,0303 ]   [ 14 queries used ]   [ Generated: 21.05.24, 19:05 GMT ]