简体   繁体   中英

checking if it is windows or unix before creating a directory in C++

I wrote this piece of code to check if a directory exists in both Windows and Unix, but I'm not sure whether it is correct:

int writeFiles(std::string location)
{

        // USED TO FILE SYSTEM OPERATION
        struct stat st;
        // DEFINE THE mode WHICH THE FILE WILL BE CREATED
        const char * mode = "w+b";
        /* local curl variable */

        // CHECK IF THE DIRECTORY TO WHERE THE FILE ARE GOING EXIST
        // IF NOT, CREATE IT
        if(stat(location.c_str(), &st) != 0){
                #ifndef (defined  _WIN32 || defined __WIN64)    /* WIN32 SYSTEM */
                if (!CreateDirectory(location.c_str(), NULL)){
                        std::string msg("The location directory did not exists, can't be created\n");
                        throw std::runtime_error(msg);
                }
                #elif defined __unix__          /* in the case of unix system */
                if(mkdir(location.c_str(), S_IRWXU) != 0){
                        std::string msg("The dest_loc directory did not exist, can't be created\n");
                        throw std::runtime_error(msg);
                }
                #endif

 ... more code down here.

location is the path to where the files are supposed to copied. However, before I start copying the files, I have to check whether the directory exists or not, for both Windows and Linux. Could someone please give me some input on that problem? Thanks

The preprocessor directives (see list of Microsoft Predefined Macros ) I would write as:

#ifdef _WIN32

#else

// Assume UNIX system,
// depending on what you are compiling your code on,
// by that I mean you only building on Windows or UNIX
// (Linux, Solaris, etc) and not on Mac or other.
#endif

The CreateDirectory() will fail (return FALSE ) if the directory already exists but will set the last error to ERROR_ALREADY_EXISTS . Change your use of CreateDirectory() to handle this correctly:

if (!CreateDirectory(location.c_str(), NULL) &&
    ERROR_ALREADY_EXISTS != GetLastError())
{
    // Error message more useful if you include last error code.
    std::ostringstream err;
    err << "CreateDirectory() failure on "
        << location
        << ", last-error="
        << GetLastError();

    throw std::runtime_exception(err.str());
}

Having said that, if you have access to boost consider using the boost::filesystem library.

You need to change:

            #ifndef (defined  _WIN32 || defined __WIN64)    /* WIN32 SYSTEM */

to:

            #if (defined _WIN32 || defined __WIN64)    /* WIN32 SYSTEM */

This tests whether either _WIN32 or __WIN64 is defined and then uses the WINAPI code if that is the case.

You could probably also change:

            #elif defined __unix__          /* in the case of unix system */

to just:

            #else          /* in the case of non-Windows system */

since most non-Windows OS are likely to have POSIX-ish APIs for mkdir etc, and you currently don't have any other OS-specific code.

如果必须编写与文件系统交互的跨平台代码,则可以使用跨平台文件系统API,例如Boost FileSystem

If you can assume that Windows has stat() , why can't you also just use mkdir() ?

But really, on Windows you can call CreateDirectory unconditionally (no preceding stat call) and check whether GetLastError() returns ERROR_ALREADY_EXISTS .

Also, std::string is a match for the ANSI function, CreateDirectoryA . Using the CreateDirectory macro leaves you open to Unicode mismatch.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM