0

Here's my situation: I'm using SimpleIni to open a settings.ini file, but in some cases this file might not exist. If it doesn't exist, then I want to create it. Here's the thing, though, I need this file to be in the user directory, not the install directory. The full filename for the file is:

C:\Users\Haydn\AppData\Roaming\CompanyName\AppName\settings.ini

Problem is, the CompanyName folder might not even exist. If SimpleIni fails to open the file, then the most common case is that the file doesn't exist, and I want to make it exist and then try again (even an empty file works).

The only libraries I'm using right now are SDL and SimpleIni. I want to avoid using platform-specific code, but would prefer not to link to Boost.

(Note: that path string was created by SDL, it would be different on linux or mac)

Haydn V. Harach
  • 1,265
  • 1
  • 18
  • 36

2 Answers2

0

I am doing INI read/write in this way (when the Ini file is inside the application folder):

void CDlgApplication::ReadSettings()
{
     CString IniPath = m_appDir ;
     IniPath += _T("Settings.ini") ;

     if(!FileExists(IniPath))
       return ;

     CIniReader iniReader(IniPath);
     //... do the settings read....
 }


 void CDlgApplication::SaveSettings()
 {
    GetParams();

    CString IniPath = m_appDir ;
    IniPath += _T("Settings.ini") ;
    CIniWriter iniWriter(IniPath);

    //... do the settings save....
 }

Where:

 bool FileExists(LPCTSTR szPath) 
 {  
    DWORD dwAttrib = GetFileAttributes(szPath); 
    return (bool)((dwAttrib != -1) && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
 } 

In your case if the INI file is in different than the application folder and you are not sure that this folder exists you can suppiy the folder path to SaveSettings() and use some API like Win32 MakeSureDirectoryPathExists():

 void CDlgApplication::SaveSettings(const TCHAR* OutputFolder)
 {
    if(!MakeSureDirectoryPathExists(OutputFolder))
      return ; //Maybe report error or save the INI somewhere else

    GetParams();

    CString IniPath =OutputFolder ;
    IniPath += _T("Settings.ini") ;
    CIniWriter iniWriter(IniPath);

    //... do the settings save....
 }

If you do not have MakeSureDirectoryPathExists() you can easy write your owm function recursively creating folders using mkdir. It is too long to post it here.

Baj Mile
  • 750
  • 1
  • 8
  • 17
  • I'm not using WinAPI. I use SDL for windowing, and anything else I handle it as the situation arises. I need my solution to be cross-platform. I'll look into mkdir, though. – Haydn V. Harach Aug 04 '14 at 20:24
  • See: http://stackoverflow.com/questions/675039/how-can-i-create-directory-tree-in-c-linux, I have not tested but it seems cross-platform. – Baj Mile Aug 04 '14 at 20:30
0

Unfortunately there is no platform-independent way of creating a directory. Most platform will have a mkdir() function. On windows you can use _mkdir(char*), but the parent directory must exist.

So to create a path you have to split the path until you find an existing directory (worst case : start from the root). Then create each subfolder.

A "straightforward" way is to loop backward from the end of the path, find an existing directory and create all the subfolders:

size_t slashPos = 0;
size_t lastSlashPos = 0;

size_t I = strlen(filepath) + 1;
size_t i;

for (i = I-1; i<I; --i) {
    if (filepath[i] == '\\') {
        if (lastSlashPos) filepath[lastSlashPos] = '\\'
        lastSlashPos = slashPos;
        slashPos = i;
        filepath[i] = 0;
        if (/*test for filePath existance*/) {
            break;
        }
    }
}

for (; i<I; ++i) {
    if (filepath[i] == '\\') {
        if (lastSlashPos) filepath[lastSlashPos] = '\\'
        lastSlashPos = slashPos;
        slashPos = i;
        filepath[i] = 0;
        _mkdir(filepath); //TODO : Test for success
    }
}

if (lastSlashPos) filepath[lastSlashPos] = '\\'; //if you need to restore the original string

This code have been improvised while writing this answer and have a 80% probability of being wrong.

It also assumes the drive exists.

ThreeStarProgrammer57
  • 2,906
  • 2
  • 16
  • 24