Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Создание директории


Автор: VSB 17.7.2010, 12:21
Написал функцию для создания вложенных директорий, но не уверен, что правильно.
Посмотрите, пожалуйста
Код

#define MY_MAX_PATH 32768    //REAL NTFS MAX_PATH
#define UNC_PREFIX L"\\\\?\\" 


BOOL my_CreateDirectoryW(
                         __in     LPCWSTR lpPathName,
                         __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes
                         )
{
    WCHAR *tmpchr;
    WCHAR tmpDir[MY_MAX_PATH];
    wcscpy_s(tmpDir,MY_MAX_PATH,lpPathName);
    WCHAR tmpUpDir[MY_MAX_PATH];
    wcscpy_s(tmpUpDir,MY_MAX_PATH,lpPathName);
    if (wcslen(wcsrchr(tmpUpDir,L'\\'))==1)
    {
        tmpchr=wcsrchr(tmpUpDir,L'\\');
        *tmpchr=L'\0';
    } 
    tmpchr=(WCHAR *)((DWORD)wcsrchr(tmpUpDir,L'\\')+sizeof(WCHAR));                //we need the last character
    *tmpchr=L'\0';
    if (!PathFileExistsW(tmpUpDir))                                                //there is no upper directory, try to create in
    {
        if ((wcscmp(tmpUpDir,tmpDir)==0)||(wcscmp(tmpUpDir,UNC_PREFIX)==0))        //there can't be upper directory
        {
            SetLastError(ERROR_PATH_NOT_FOUND);
            return FALSE;
        } 
        else                                                                    //there can be
        {
            return my_CreateDirectoryW(tmpUpDir,lpSecurityAttributes);
        }
    }
    else
    {
        return CreateDirectoryW(tmpDir,lpSecurityAttributes);                    //hl may be created only in existing directory
    }
}

Автор: 586 17.7.2010, 12:28
А ведь такая функция есть... http://msdn.microsoft.com/en-us/library/bb762130%28VS.85%29.aspx

Автор: VSB 17.7.2010, 12:34
Я знаю, но во первых
Цитата

pszPath [in] 
LPCWSTR

A pointer to a null-terminated Unicode string that contains the fully-qualified path of the directory. This string should have no more than MAX_PATH characters, including the terminating NULL character.


И ещё
Цитата

Note  This function is available through Windows XP Service Pack 2 (SP2) and Windows Server 2003. It might be altered or unavailable in subsequent versions of Windows.


Так что не подходит.
Нужна поддержка длинных путей (#define MY_MAX_PATH 32768    //REAL NTFS MAX_PATH) и работоспособность на всех NT 5.0+

Автор: boostcoder 17.7.2010, 12:40
как-то муторно у вас получилось..
есть http://www.boost.org/doc/libs/1_43_0/libs/filesystem/doc/reference.html#Convenience-functions

если уж очень хочется поизвращаться, то как-то так:
Код

void create_directories(const std::string& path) {
   std::string cur;
   std::vector<std::string> paths;

   if ( path[0] == '/' ) { cur += "/"; }

   boost::algorithm::split(paths, path, boost::algorithm::is_any_of("\\/"));
   for ( std::vector<std::string>::iterator it = paths.begin(); it != paths.end(); ++it ) {
      cur += *it;
      if ( !boost::filesystem::exists(cur) ) {
         boost::filesystem::create_directory(cur);
      }
      cur += "/";
   }
}

Автор: VSB 17.7.2010, 12:51
НУ, мне нужна поддержку длинных путей (начало вида \\?\c:\...) и вход через wchar_t*

Автор: boostcoder 17.7.2010, 12:52
Цитата(VSB @ 17.7.2010,  12:51)
НУ, мне нужна поддержку длинных путей (начало вида \\?\c:\...) и вход через wchar_t*

и?

Добавлено через 55 секунд
Цитата(VSB @  17.7.2010,  12:51 Найти цитируемый пост)
\\?\c:\

а что это означает?

Автор: VSB 17.7.2010, 13:05
>а что это означает?

http://msdn.microsoft.com/en-us/library/aa365247(v=VS.85).aspx#maxpath

Этот префикс (\\?\) при вызове к уникодным версиям некоторых функций (например, http://msdn.microsoft.com/en-us/library/aa363855(VS.85).aspx) обойти ограничение MAX_PATH в 260 символов

Автор: boostcoder 17.7.2010, 13:14
Цитата(VSB @  17.7.2010,  13:05 Найти цитируемый пост)
обойти ограничение MAX_PATH в 260 символов

в приведенном мною примере, никаких ограничений быть не может. разве что, ограничение на объем памяти smile 

Автор: VSB 17.7.2010, 13:22
Тем не менее, мне нужна полная поддержка wchar_t

Добавлено через 1 минуту и 23 секунды
Цитата(boostcoder @  17.7.2010,  13:14 Найти цитируемый пост)
в приведенном мною примере, никаких ограничений быть не может. разве что, ограничение на объем памяти  

Вы уверены?
А через какие системные вызовы оно работает на самом деле?

Автор: boostcoder 17.7.2010, 13:47
Цитата(VSB @  17.7.2010,  13:22 Найти цитируемый пост)
Тем не менее, мне нужна полная поддержка wchar_t

дак замени std::string на std::wstring

Цитата(VSB @  17.7.2010,  13:22 Найти цитируемый пост)
А через какие системные вызовы оно работает на самом деле?

CreateDirectoryW()

как я понял из описания CreateDirectoryA(), для поддержки длинных путей, нужно всего лишь сделать префикс "\\?\"

в таком случае, функция приобретает вид:
Код

void create_directories(const std::wstring& path) {
   std::wstring cur(L"\\\\?\\"), tmp(path);
   std::vector<std::wstring> paths;

   std::wstring::iterator it = std::find(tmp.begin(), tmp.end(), L':');
   if ( it != tmp.end() ) {
      cur += std::wstring(tmp.begin(), it+2);
      tmp = std::wstring(it+2, tmp.end());
   }

   boost::algorithm::split(paths, tmp, boost::algorithm::is_any_of(L"\\/"));
   for ( std::vector<std::wstring>::iterator it = paths.begin(); it != paths.end(); ++it ) {
      cur += *it;
      if ( !boost::filesystem::exists(cur) ) {
         boost::filesystem::create_directory(cur);
      }
      cur += L"/";
   }
}

проверил на длине пути 4096. работает. 

Автор: VSB 17.7.2010, 19:17
И тем не менее, я ничего не знаю про boost, итераторы и не шарю в шаблонах, так что когда разберусь - может и запользую.
А пока, просто скажите, правильно ли я написал?

Автор: boostcoder 17.7.2010, 20:06
Цитата(VSB @  17.7.2010,  19:17 Найти цитируемый пост)
И тем не менее, я ничего не знаю про boost, итераторы и не шарю в шаблонах, так что когда разберусь - может и запользую.

и нафига я тут распинался? smile 
все равно спасибо.

Автор: VSB 18.7.2010, 01:10
Цитата(boostcoder @  17.7.2010,  20:06 Найти цитируемый пост)
и нафига я тут распинался?  


Ну извините, что так получилось.
Просто если я сейчас начну разбираться с boost и шаблонами, то не закончу этот плагин (для которого функция) в обозримом будущем.
А нужно.

Но всё равно спасибо.

=========

По функции интересует, не будет ли тут ошибок по логике (и ошибок вообще) и будет ли в результате GetLastError() соответствовать таковому от последнего вызова к CreateDirectoryW?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)