Рекурсивно создавать путь в c в ОС Windows [duplicate]

Для этого мы можем использовать этот форматтер:

 DecimalFormat df = new DecimalFormat("#.00");
 String resultado = df.format(valor)

или:

DecimalFormat df = new DecimalFormat("0.00"); :

Используйте этот метод для получения двух десятичных знаков:

   private static String getTwoDecimals(double value){
      DecimalFormat df = new DecimalFormat("0.00"); 
      return df.format(value);
    }

Определение этих значений:

91.32
5.22
11.5
1.2
2.6

Используя этот метод, мы можем получить следующие результаты:

91.32
5.22
11.50
1.20
2.60

demo online.

30
задан pauldoo 7 October 2009 в 11:28
поделиться

13 ответов

Примечание: этот ответ несколько быстрый и грязный, и он не обрабатывает все случаи. Если с вами все в порядке, читайте дальше. Если нет, подумайте об использовании одного из других вариантов.


Для этого вы можете использовать добрый старый mkdir. Просто запустите

system("mkdir " + strPath);

, и все готово.

Ну, почти. Есть еще случаи, о которых вам нужно позаботиться, например, об общих долях сети (которые могут не сработать) и обратных косых чертах. Но при использовании относительно безопасных путей вы можете использовать эту более короткую форму.

Еще одна вещь, которая может оказаться полезной для избавления от возможной неприятности, - _fullpath () , которая разрешит данный путь в полный и чистый. Зная, что у вас есть чистый путь, у вас не должно возникнуть проблемы с написанием довольно тривиальной рекурсивной функции, которая будет создавать папки по одному, даже при работе с UNC-путями.

-10
ответ дан eran 22 August 2018 в 08:11
поделиться
  • 1
    Я не горжусь этим, но это было решение, по которому мы шли. Очень короткое, работает для сетевых ресурсов. Просто слишком легко игнорировать. – pauldoo 8 October 2009 в 20:15
  • 2
    +1 - Я думаю, что это на самом деле очень прагматичное решение, и действительно - у mkdir уже много сложных проблем. – Frerich Raabe 18 September 2012 в 14:45
  • 3
    Стоит отметить, что это решение не поддерживает пути Unicode и имеет очень дорогостоящий процесс, созданный под Windows, действительно очень дорогостоящая операция. Кроме того, избегая аргументов в этой форме, безусловно, нетривиально. Вы можете избежать всех этих проблем (за исключением высокой производительности) с помощью CreateProcessW. – EFraim 3 March 2013 в 16:56
  • 4
    @FrerichRaabe: Это очень неправильное решение, потому что в нем много неочевидных проблем, которые вряд ли проявятся в тестировании, но почти наверняка будут в производственной среде. – EFraim 3 March 2013 в 17:05
  • 5
    @EFraim: Дело не столько в использовании system вместо CreateProcess; речь идет о вызове программы mkdir в первую очередь. – Frerich Raabe 3 March 2013 в 20:31

Функция SHCreateDirectory может это сделать. Но в документе указано, что он может устареть в более поздней версии Windows.

Из MSDN

Примечание. Эта функция доступна через Windows XP с пакетом обновления 2 (SP2) и Microsoft Windows Server 2003. Он может быть изменен или недоступен в последующих версиях Windows.

6
ответ дан Aamir 22 August 2018 в 08:11
поделиться
void createFolders(const std::string &s, char delim) {
    std::stringstream ss(s);
    std::string item;
    char combinedName[50]={'\0'};
    while (std::getline(ss, item, delim)) { 
        sprintf(combinedName,"%s%s%c",combinedName,item.c_str(),delim);
        cout<<combinedName<<endl;

        struct stat st = {0};
                 if (stat(combinedName,&st)==-1)
                 { 
            #if REDHAT
                     mkdir(combinedName,0777);
            #else
                      CreateDirectory(combinedName,NULL);
            #endif
                 }


     }
}
-1
ответ дан Awais Rafique 22 August 2018 в 08:11
поделиться
  • 1
    Не могли бы вы добавить текст, чтобы объяснить свой ответ? – Kmeixner 14 April 2016 в 13:50
  • 2
    createFloders (& Quot; A / B / C / D / E & Quot;, '/'); – Awais Rafique 15 April 2016 в 08:46

Вот мой пример кода (скопирован из Как я могу создать дерево каталогов в C ++ / Linux? ). Возможно, он не соответствует всем требованиям с первого поста, но довольно хорошо, и он работает как для Windows, так и для Linux:

#include <iostream>
#include <string>
#include <sys/stat.h> // stat
#include <errno.h>    // errno, ENOENT, EEXIST
#if defined(_WIN32)
#include <direct.h>   // _mkdir
#endif

bool isDirExist(const std::string& path)
{
#if defined(_WIN32)
    struct _stat info;
    if (_stat(path.c_str(), &info) != 0)
    {
        return false;
    }
    return (info.st_mode & _S_IFDIR) != 0;
#else 
    struct stat info;
    if (stat(path.c_str(), &info) != 0)
    {
        return false;
    }
    return (info.st_mode & S_IFDIR) != 0;
#endif
}

bool makePath(const std::string& path)
{
#if defined(_WIN32)
    int ret = _mkdir(path.c_str());
#else
    mode_t mode = 0755;
    int ret = mkdir(path.c_str(), mode);
#endif
    if (ret == 0)
        return true;

    switch (errno)
    {
    case ENOENT:
        // parent didn't exist, try to create it
        {
            int pos = path.find_last_of('/');
            if (pos == std::string::npos)
#if defined(_WIN32)
                pos = path.find_last_of('\\');
            if (pos == std::string::npos)
#endif
                return false;
            if (!makePath( path.substr(0, pos) ))
                return false;
        }
        // now, try to create again
#if defined(_WIN32)
        return 0 == _mkdir(path.c_str());
#else 
        return 0 == mkdir(path.c_str(), mode);
#endif

    case EEXIST:
        // done!
        return isDirExist(path);

    default:
        return false;
    }
}

int main(int argc, char* ARGV[])
{
    for (int i=1; i<argc; i++)
    {
        std::cout << "creating " << ARGV[i] << " ... " << (makePath(ARGV[i]) ? "OK" : "failed") << std::endl;
    }
    return 0;
}

Использование:

d:\Work\c++\make_path> makePath 1/2 folderA/folderB/folderC
creating 1/2 ... OK
creating folderA/folderB/folderC ... OK
-1
ответ дан Community 22 August 2018 в 08:11
поделиться
  • 1
    Без поддержки Unicode это определенно не работает в Windows. – IInspectable 2 February 2016 в 12:41

Если вам не нужно поддерживать версии Windows до Windows 2000, для этого вы можете использовать функцию SHCreateDirectoryEx . Рассмотрим это:

int createDirectoryRecursively( LPCTSTR path )
{
    return SHCreateDirectoryEx( NULL, path, NULL );
}

// ...
if ( createDirectoryRecursively( T("C:\\Foo\\Bar\\Baz") ) == ERROR_SUCCESS ) {
   // Bingo!
} 

Если использование такого API shell32.dll когда-либо становится проблемой, вы всегда можете переопределить функцию createDirectoryRecursively выше с чем-то другим (возможно, с проводкой в ​​ручном режиме).

43
ответ дан Frerich Raabe 22 August 2018 в 08:11
поделиться
  • 1
    Слово предупреждения о том, что SHCreateDirectoryEx имеет особое поведение при работе со скрытыми каталогами и может показывать пользователю диалоговые окна пользовательского интерфейса. – ShadowChaser 8 March 2012 в 23:16
  • 2
    Он показывает только диалог пользовательского интерфейса, если передается ссылка hwnd, а не если она равна NULL. – Joakim 13 December 2012 в 15:07
  • 3
    @Joakim: Даже если HWND NULL, вы можете оказаться в неприятном сюрпризе, потому что он МОЖЕТ обрабатывать сообщения без очереди. – EFraim 3 March 2013 в 16:53
  • 4
    Он не работает с относительными путями ... – AntonK 17 July 2017 в 16:42
  • 5
    Также SHCreateDirectoryEx не может обрабатывать дорожки дольше, чем MAX_PATH (префикс "\\?\"). – zett42 9 October 2017 в 16:57

Вот функция, которую я написал, которая итеративно создает дерево папок. Вот основная функция:

#include <io.h>
#include <string>
#include <direct.h>
#include <list>

// Returns false on success, true on error
bool createFolder(std::string folderName) {
    list<std::string> folderLevels;
    char* c_str = (char*)folderName.c_str();

    // Point to end of the string
    char* strPtr = &c_str[strlen(c_str) - 1];

    // Create a list of the folders which do not currently exist
    do {
        if (folderExists(c_str)) {
            break;
        }
        // Break off the last folder name, store in folderLevels list
        do {
            strPtr--;
        } while ((*strPtr != '\\') && (*strPtr != '/') && (strPtr >= c_str));
        folderLevels.push_front(string(strPtr + 1));
        strPtr[1] = 0;
    } while (strPtr >= c_str);

    if (_chdir(c_str)) {
        return true;
    }

    // Create the folders iteratively
    for (list<std::string>::iterator it = folderLevels.begin(); it != folderLevels.end(); it++) {
        if (CreateDirectory(it->c_str(), NULL) == 0) {
            return true;
        }
        _chdir(it->c_str());
    }

    return false;
}

Подпрограмма folderExists выглядит следующим образом:

// Return true if the folder exists, false otherwise
bool folderExists(const char* folderName) {
    if (_access(folderName, 0) == -1) {
        //File not found
        return false;
    }

    DWORD attr = GetFileAttributes((LPCSTR)folderName);
    if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) {
        // File is not a directory
        return false;
    }

    return true;
}

Пример вызова, который я тестировал выше, имеет следующее (и это работает):

createFolder("C:\\a\\b\\c\\d\\e\\f\\g\\h\\i\\j\\k\\l\\m\\n\\o\\p\\q\\r\\s\\t\\u\\v\\w\\x\\y\\z");

Эта функция не прошла тщательного тестирования, и я не уверен, что она еще работает с другими операционными системами (но, вероятно, совместима с несколькими модификациями). В настоящее время я использую Visual Studio 2010 с Windows 7.

7
ответ дан Jonathan Feucht 22 August 2018 в 08:11
поделиться
  • 1
    Это работает на первый взгляд, но он изменяет текущий каталог на вновь созданный, что, возможно, не произойдет, если вы используете относительные пути. – antipattern 13 January 2015 в 15:18
  • 2
    Не использовать Unicode - это преступление, которое произошло в течение этого тысячелетия. Не знаете, почему вы передали первый аргумент GetFileAttributes тому же самому типу, который он также передал. – IInspectable 2 February 2016 в 12:32

Вот версия, которая работает без внешних библиотек, поэтому только для Win32 и для всех версий Windows (включая Windows CE, где мне это нужно):

wchar_t *path = GetYourPathFromWherever();

wchar_t folder[MAX_PATH];
wchar_t *end;
ZeroMemory(folder, MAX_PATH * sizeof(wchar_t));

end = wcschr(path, L'\\');

while(end != NULL)
{
    wcsncpy(folder, path, end - path + 1);
    if(!CreateDirectory(folder, NULL))
    {
        DWORD err = GetLastError();

        if(err != ERROR_ALREADY_EXISTS)
        {
            // do whatever handling you'd like
        }
    }
    end = wcschr(++end, L'\\');
}
9
ответ дан Julien Ruffin 22 August 2018 в 08:11
поделиться
  • 1
    Выглядит неплохо, но если я правильно его читаю, для этого требуется, чтобы путь имел хвост & quot; \ & quot ;, в противном случае путь, подобный "C: \ folder \ subfolder & quot; не будет создавать «подпапку», но «C: \nапка \nодпапка» & quot; будем. Вероятно, вам понадобится дополнительный вызов CreateDirectory (путь) после завершения цикла. – Remy Lebeau 27 May 2016 в 22:22
  • 2
    Это предназначалось для получения полностью квалифицированного пути к файлу, и это гарантирует, что папка для цели существует. Если вы хотите передать только путь к папке, то да, это потребует дальнейшей работы – ctacke 28 May 2016 в 17:26
UnicodeString path = "C:\\Test\\Test\\Test\\";
TStringList *list = new TStringList();

try
{
    list->Delimiter = '\\';
    list->StrictDelimiter = true;
    list->DelimitedText = path;
    path = list->Strings[0]; \\drive letter
    for(int i = 1; i < list->Count - 1; i++)
    {
        try
        {
            path += "\\" + list->Strings[i];
            CreateDirectory(path.w_str(), NULL);
        }
        catch(...) { }
    }
}
catch(...) { }
delete list;
0
ответ дан rebeldevil14 22 August 2018 в 08:11
поделиться

удобная и простая рабочая версия моей:

BOOL DirectoryExists(LPCTSTR szPath)
{
  DWORD dwAttrib = GetFileAttributes(szPath);

  return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
    (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}

void createDirectoryRecursively(std::wstring path)
{
  unsigned int pos = 0;
  do
  {
    pos = path.find_first_of(L"\\/", pos + 1);
    CreateDirectory(path.substr(0, pos).c_str(), NULL);
  } while (pos != std::string::npos);
}

//in application
int main()
{
  std::wstring directory = L"../temp/dir";
  if (DirectoryExists(directory.c_str()) == FALSE)
    createDirectoryRecursively(directory);
  return 0;
}
3
ответ дан sailfish009 22 August 2018 в 08:11
поделиться

ctacke Вы забыли последний сегмент. например '\ aa \ bb \ "cc"' Ниже приведена модификация для ctacke:

//---------------------------------------------------------------------
int isfexist(char *fn)
{
    struct stat stbuf;
    extern int errno;

    if (stat(fn, &stbuf)) {
        if (errno == ENOENT) return(0);
        else {
            printf("isfexist: stat");
            return(0);
        }
    } else {
        if (stbuf.st_mode & S_IFDIR) return(2);
        else return(1);
    }
}
//---------------------------------------------------------------------
int MakeDirTree(char *path)
{
    char *end1, *end2;

    if (path[0] == '\\') end1 = path + 1;       // Case '\aa\bb'
    else if (path[1] == ':' && path[2] == '\\') end1 = path + 3;    // Case 'C:\\aa\\bb'
    else end1 = path;

    for(;;) {
        end2 = strchr(end1, '\\');
        if (end2 == NULL) {
            // Case '\aa\bb\'
            if (*end1 == 0) break;
            // Last segment '\aa\bb\"cc"' not yet proceed
        } else *end2 = 0;
        if (isfexist(path) <= 0) mkdir(path);
        if (end2 == NULL) break;    // Last segment finished
        else {
            *end2 = '\\';
            end1 = end2 + 1;
        }
    }
}
1
ответ дан steel17 22 August 2018 в 08:11
поделиться

Я изменяю старое приложение Windows CE, и это то, что я планирую использовать. Должен работать и в Windows CE. Это тоже рекурсивно:

static void createPath(const CString& p)
{
   // only create directories that don't exist
   if (::GetFileAttributes(p) == INVALID_FILE_ATTRIBUTES)
   {
      // check if our parent needs to be created, too...
      int i = p.ReverseFind('\\');
      if (i > 0)
      {
         // ...yes, create the parent (recursively)
         createPath(p.Left(i));
      }

      // finally, actually create the directory in p
      ::CreateDirectory(p, NULL);
   }
}
1
ответ дан Tommi 22 August 2018 в 08:11
поделиться
  • 1
    У меня действительно была возможность проверить это на Win32 и WinCE, похоже, работает нормально. – Tommi 13 November 2014 в 16:09
  • 2
    отлично работает для меня. – Explorer_N 22 February 2016 в 11:11

Для Windows XP и выше. Ожидает, что строка с нулевым символом завершена и количество рекурсивных действий в качестве параметров.

Примечание: Сепараторы пути должны быть «\»

bool CreateRecursiveDirectoryW(const wchar_t* filepath, const int max_level)
{
    bool result = false;
    wchar_t path_copy[MAX_PATH] = {0};
    wcscat_s(path_copy, MAX_PATH, filepath);
    std::vector<std::wstring> path_collection;

    for(int level=0; PathRemoveFileSpecW(path_copy) && level < max_level; level++)
    {
        path_collection.push_back(path_copy);
    }
    for(int i=path_collection.size()-1; i >= 0; i--)
    {
        if(!PathIsDirectoryW(path_collection[i].c_str()))
            if(CreateDirectoryW(path_collection[i].c_str(), NULL))
                result = true;
    }
    return result;
};
2
ответ дан xezon 22 August 2018 в 08:11
поделиться

Из http://www.cplusplus.com/reference/string/string/find_last_of/ :

// string::find_last_of
#include <iostream>
#include <string>
using namespace std;

void SplitFilename (const string& str)
{
  size_t found;
  cout << "Splitting: " << str << endl;
  found=str.find_last_of("/\\");
  cout << " folder: " << str.substr(0,found) << endl;
  cout << " file: " << str.substr(found+1) << endl;
}

int main ()
{
  string str1 ("/usr/bin/man");
  string str2 ("c:\\windows\\winhelp.exe");

  SplitFilename (str1);
  SplitFilename (str2);

  return 0;

Это должно дать вам представление о том, как справиться с строкой пути. Затем после этого все, что вам нужно сделать, - это цикл через пути, начиная с диска и заканчивая самой глубокой папкой. Проверьте, существует ли папка, а если нет, создайте ее.

-1
ответ дан xian 22 August 2018 в 08:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: