CreatePath - Full Path Creation (wstring version)

Environment: Visual C++

This is a simple function I wrote in order to deal with creating complete (multi-level) paths.

The function works recursively, and uses std::wstring, but can actaully work on any basic_string -based string. It can deal with trailing slashes (eg. "c:\temp\" vs. "c:\temp"), as well as network locations (eg. "\\machine\shared").

You might notice the call to SetLastError(). The reason is to make it easy to verify what went wrong in case of an error - instead of handling exceptions and/or error strings, all you have to do is call GetLastError() if the function returns false.

You can use the function to make sure a directory exists before creating a file in it:

  std::wstring wsFileName;
  int pos = wsFileName.find_last_of(L"\\");
  if (0 <= pos)
  {
    std::wstring wsPath = wsFileName.substr(0, pos);

    if (CreatePath(wsPath))
    {
      CreateFileW(wsFileName.c_str(), ...);
    }
    else
    {
      std::wcout << L"Error #" << GetLastError() << std::endl;
    }
  }

Here is the source code:
bool CreatePath(std::wstring &wsPath)
{
  DWORD attr;
  int pos;
  bool result = true;

  // Check for trailing slash:
  pos = wsPath.find_last_of(SLASH);
  if (wsPath.length() == pos + 1)  // last character is "\"
  {
    wsPath.resize(pos);
  }

  // Look for existing object:
  attr = GetFileAttributesW(wsPath.c_str());
  if (0xFFFFFFFF == attr)  // doesn't exist yet - create it!
  {
    pos = wsPath.find_last_of(SLASH);
    if (0 < pos)
    {
      // Create parent dirs:
      result = CreatePath(wsPath.substr(0, pos));
    }
    // Create node:
    result = result && CreateDirectoryW(wsPath.c_str(), NULL);
  }
  else if (FILE_ATTRIBUTE_DIRECTORY != attr)
  {  // object already exists, but is not a dir
    SetLastError(ERROR_FILE_EXISTS);
    result = false;
  }

  return result;
}

Downloads

Download source - < 1Kb


Comments

  • yFxhAE gp Og Efp lrYb Pr

    Posted by YCtBTCuwiU on 01/27/2013 03:51am

    buy generic viagra buy cheap viagra online us - viagra stories

    Reply
  • This is my piece of code for the same prupose. You forgot an important thing.

    Posted by Legacy on 02/13/2004 12:00am

    Originally posted by: My code

    I think my code is better and more efficient.
    Don't forget to consider other language.
    The '\\' caracter may be part of multibyte character in other language like Chinese.
    Use CharNextExA instead.

    void LoopCreateDirectory(LPSTR dpath)
    {
    LPSTR pname;
    for( LPSTR pdir=pname=dpath; *pdir; pdir=CharNextExA(CP_ACP,pdir,0))
    if(*pdir=='\\')
    {
    *pdir=0;
    CreateDirectory(pname,NULL);
    *pdir='\\';
    }
    }

    Reply
  • Problem with GetFileAttributes and similar functions

    Posted by Legacy on 10/25/2002 12:00am

    Originally posted by: Madbawa

    These functions have a problem when the supplied path contains a double slash ('\\') somewhere in the middle. I deliberately put the \\ to test invalid paths, but sadly it doesn't give an INVALID_HANDLE or NULL pointer.

    Reply
  • Similar but cheaper and faster iterative solution

    Posted by Legacy on 06/10/2002 12:00am

    Originally posted by: Arbesto Pelta

    Hi!,
    
    

    Reading the code implemented by Assaf Tzur-El. I see that it is a recursive algorithm,
    and that every recursive call has the cost of construct a new string
    in the stack.

    Well I know that maybe this is not a critical question but I think it is a pity the
    recusion overload unnecessarily.

    I propose the next similar but iterative solution,

    Thanks,

    Arbesto

    The code...

    bool CreatePath(const char* PathToCreate)
    {
    char Path[_MAX_PATH];
    // Copy path because we have to modify it
    strcpy(Path,PathToCreate);
    // First add an ending slash
    char* Pos = strrchr(Path,'\\');
    if (!Pos || Pos[1]!=0)
    strcat(Path,"\\");
    // From the first slash to the last check and create path
    // Exception : Jump initial duble slashed UNC host name and include first directory
    if (Path[0]=='\\' && Path[1]=='\\')
    {
    // Find slash ending the host name
    Pos = strchr(Path+2,'\\');
    // Find slash after the first directory (after the host name)
    if (Pos)
    Pos = strchr(Pos+1,'\\');
    }
    else
    Pos = strchr(Path,'\\');
    bool AllOk = true;
    while (Pos && AllOk)
    {
    // Cut the string
    *Pos = 0;
    // Check if exist this piece of path
    if (GetFileAttributes(Path)==-1)
    if (GetLastError()==ERROR_FILE_NOT_FOUND)
    AllOk = CreateDirectory(Path,NULL)==TRUE;
    else
    AllOk = false;
    // Recover the character deleted
    *Pos = '\\';
    // Find next slash
    Pos = strchr(Pos+1,'\\');
    }
    // Return true if finally the path was created or exist
    // (if not was created see LastError)
    return AllOk;
    }

    Reply
  • Funny no one mentioned it so far...

    Posted by Legacy on 06/09/2002 12:00am

    Originally posted by: Assaf Tzur-El

    ... but you might create yourself a small bug if you try to use the wsPath parameter after the function returns. The function takes its string parameter by reference, but it's NOT const, so the path might be changed inside the function. If you rely on the path staying the same, you might have a bug (your own bug, by the way, not mine - you should always check const-ness :) )

    The fix is simple - remove the reference char, and make the function look like this:
    bool CreatePath(std::wstring wsPath)

    Please note that if the function should be thread-safe and you are using Microsoft's STL, you should explicitly copy the string before passing it to the function. The reason is MS's obscene handling of reference counter for strings, which is NOT thread-safe. Feel free to email me for more information about this.

    Share and Enjoy,
    Assaf.

    Reply
  • Use MakeSureDirectoryPathExists

    Posted by Legacy on 01/16/2002 12:00am

    Originally posted by: Andrew

    Why not?

    BOOL MakeSureDirectoryPathExists(PCSTR DirPath);

    See MSDN Platform SDK

    Reply
  • Why BOOL and GetLastError?

    Posted by Legacy on 01/16/2002 12:00am

    Originally posted by: NortonNealson

    Nice function, but I have a more general question.

    What makes you return a BOOL and then when FALSE require the caller to call GetLastError instead of just returning an error number or zero for success?

    I have nothing against using Get/SetLastError but feel it should be used when the return value cannot be used to indicate success and an error number. For example a function that returns a pointer or a handle where a NULL is often used to indicate failure.

    This may just be a coding style and is my opinion. I'm interested in hearing what you and others think about this.
    Thanks,

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • "Security" is the number one issue holding business leaders back from the cloud. But does the reality match the perception? Keeping data close to home, on premises, makes business and IT leaders feel inherently more secure. But the truth is, cloud solutions can offer companies real, tangible security advantages. Before you assume that on-site is the only way to keep data safe, it's worth taking a comprehensive approach to evaluating risks. Doing so can lead to big benefits.

  • Hybrid cloud platforms need to think in terms of sweet spots when it comes to application platform interface (API) integration. Cloud Velocity has taken a unique approach to tight integration with the API sweet spot; enough to support the agility of physical and virtual apps, including multi-tier environments and databases, while reducing capital and operating costs. Read this case study to learn how a global-level Fortune 1000 company was able to deploy an entire 6+ TB Oracle eCommerce stack in Amazon Web …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds