Thread: How to open file from program's dir

  1. #1
    Registered User
    Join Date
    Sep 2006
    Posts
    230

    How to open file from program's dir

    Hello,

    I have this program that I'm trying to improve and I have to open a file for reading. The problem is, I have to specify where to get the file from.

    For some time, I just kept it at C:\ but I don't like to force the user to put the file under C.

    I could ask for the location of the file but then I'll have to input the whole path.

    I think the best way is to just ask for the file's name and open it from the directory the program is running from.

    The thing is, I don't know how. How can I tell the program to look in the directory it's running from? All I know is how to open it from a fixed specific location (e.g. C:\Program\ ).

    All help is appreciated. Thank you

  2. #2
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    I found some code for this. I did not write it (I probably found it on this site actually), and it requires Windows:
    Code:
    // xtree.cpp : Defines the entry point for the console application.
    //
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <windows.h> 
    
    void errormessage(void)
    {
      LPVOID  lpMsgBuf;
      FormatMessage
      (
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        GetLastError(),
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),  // Default language
        (LPTSTR) & lpMsgBuf,
        0,
        NULL
      );
      fprintf(stderr, "%s\n", (char*)lpMsgBuf);
      LocalFree(lpMsgBuf);
    }
    
    void format_time(FILETIME *t, char *buff)
    {
      FILETIME    localtime;
      SYSTEMTIME  sysloc_time;
      FileTimeToLocalFileTime(t, &localtime);
      FileTimeToSystemTime(&localtime, &sysloc_time);
      sprintf
      (
        buff,
        "%4d/%02d/%02d %02d:%02d:%02d",
        sysloc_time.wYear,
        sysloc_time.wMonth,
        sysloc_time.wDay,
        sysloc_time.wHour,
        sysloc_time.wMinute,
        sysloc_time.wSecond
      );
    }
    
    void format_attr(DWORD attr, char *buff)
    {
      *buff++ = attr & FILE_ATTRIBUTE_ARCHIVE ? 'A' : '-';
      *buff++ = attr & FILE_ATTRIBUTE_SYSTEM ? 'S' : '-';
      *buff++ = attr & FILE_ATTRIBUTE_HIDDEN ? 'H' : '-';
      *buff++ = attr & FILE_ATTRIBUTE_READONLY ? 'R' : '-';
      *buff++ = attr & FILE_ATTRIBUTE_DIRECTORY ? 'D' : '-';
      *buff++ = attr & FILE_ATTRIBUTE_ENCRYPTED ? 'E' : '-';
      *buff++ = attr & FILE_ATTRIBUTE_COMPRESSED ? 'C' : '-';
      *buff = '\0';
    }
    
    struct flist
    {
      int             num_entries;
      int             max_entries;
      WIN32_FIND_DATA *files;
    };
    typedef struct flist flist;
    
    void addfile(flist *list, WIN32_FIND_DATA data)
    {
      if (list->num_entries == list->max_entries)
      {
        int             newsize = list->max_entries == 0 ? 16 : list->max_entries * 2;
        WIN32_FIND_DATA *temp = (WIN32_FIND_DATA *) realloc(list->files, newsize * sizeof(WIN32_FIND_DATA));
        if (temp == NULL)
        {
          fprintf(stderr, "Out of memory\n");
          exit(1);
        }
        else
        {
          list->max_entries = newsize;
          list->files = temp;
        }
      }
    
      list->files[list->num_entries++] = data;
    }
    
    int sortfiles(const void *a, const void *b)
    {
      const WIN32_FIND_DATA *pa = (WIN32_FIND_DATA *) a;
      const WIN32_FIND_DATA *pb = (WIN32_FIND_DATA *) b;
      int                   a_is_dir = pa->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
      int                   b_is_dir = pb->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
      if (a_is_dir ^ b_is_dir)
      {
        // one of each, prefer the directories first
        if (a_is_dir) return(-1);
        if (b_is_dir) return(+1);
        return(0);
      }
      else
      {
        // both files, or both directories - return the strcmp result
        return(strcmp(pa->cFileName, pb->cFileName));
      }
    }
    
    void doit(char *root)
    {
      flist           list = { 0, 0, NULL };
      HANDLE          h;
      WIN32_FIND_DATA info;
      int             i;
    
      // build a list of files
      h = FindFirstFile("*.*", &info);
      if (h != INVALID_HANDLE_VALUE)
      {
        do
        {
          if (!(strcmp(info.cFileName, ".") == 0 || strcmp(info.cFileName, "..") == 0))
          {
            addfile(&list, info);
          }
        } while (FindNextFile(h, &info));
        if (GetLastError() != ERROR_NO_MORE_FILES) errormessage();
        FindClose(h);
      }
      else
      {
        errormessage();
      }
    
      // sort them
      qsort(list.files, list.num_entries, sizeof(list.files[0]), sortfiles);
    
      // print out in sorted order
      int numdirs = 0;
      for (i = 0; i < list.num_entries; i++)
      {
        char  t1[50], t2[50], t3[50], a[10];
        format_time(&list.files[i].ftCreationTime, t1);
        format_time(&list.files[i].ftLastAccessTime, t2);
        format_time(&list.files[i].ftLastWriteTime, t3);
        format_attr(list.files[i].dwFileAttributes, a);
        if (list.files[i].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
          // 'null' date for directory access times, which change each time
          // we run this tool
          sprintf(t2, "%4d/%02d/%02d %02d:%02d:%02d", 2000, 1, 1, 0, 0, 0);
        }
    
        printf("%s %10ld %s %s %s %s\\%s\n", a, list.files[i].nFileSizeLow, t1, t2, t3, root, list.files[i].cFileName);
        if (list.files[i].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) numdirs++;
      }
    
      // now process all the sub-dirs
      // free all the files first, to save a bit of space
      // the sort function will have put them all at the end.
      list.files = (WIN32_FIND_DATA *) realloc(list.files, numdirs * sizeof(WIN32_FIND_DATA));
      for (i = 0; i < numdirs; i++)
      {
        char  newroot[MAX_PATH];
        sprintf(newroot, "%s\\%s", root, list.files[i].cFileName);
        SetCurrentDirectory(list.files[i].cFileName);
        doit(newroot);
        SetCurrentDirectory("..");
      }
    
      // free the remainder
      free(list.files);
    }
    
    void banner(void)
    {
      //       12345678901234567890
      printf("Attribs ");
      printf("      Size ");
      printf("       CreationTime ");
      printf("     LastAccessTime ");
      printf("      LastWriteTime ");
      printf("Filename\n");
    }
    
    int main(int argc, char *argv[])
    {
      if (argc > 1)
      {
        char  olddir[MAX_PATH];
        if (GetCurrentDirectory(MAX_PATH, olddir) == 0)
        {
          errormessage();
          exit(1);
        }
    
        if (!SetCurrentDirectory(argv[1]))
        {
          errormessage();
          exit(1);
        }
    
        banner();
        doit(".");
        SetCurrentDirectory(olddir);
      }
      else
      {
        banner();
        doit(".");
      }
      getchar();
      return(0);
    }

  3. #3
    Registered User
    Join Date
    Sep 2006
    Posts
    230
    so there's no way to do it standardly to work with all OSs?

  4. #4
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    just don't specify a drive letter or root slash and it should work in the current working directory. also, on some implementations, argv[0] has the path too.

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I'm a little bit confused here.

    I thought the original poster was after something that picks out the directory from where the executable file was opened (e.g. if it's installed in "C:/program files/myapp", then you'd have some configuration file or such-like in that directory, and thus want to know where the application was started from (whcih executable is it that is running).

    MikeG then produces a rather long list of a program that lists EVERY FILE below a certain point in the file-system - not sure how that is related. It does, however, move itself (completely unnecessarily - why not just pass the requested directory to the list-function?) from the current directory to the requested directory and back agiain, using "GetCurrentDirectory()" and "SetCurrentDirectory()".

    GetCurrentDirectory, however, shows the directory in which the command was executed, not where the original binary was fetched from. Robwhit then suggests that it can be found in "argv[0]", which is indeed correct under some circumstances, but not always - certainly you can't rely on it containing anything other than the basename of the executable - not even the .exe part may be included if it's a windows .exe file.

    I'd be a bit surprised if this isn't possible to do - perhaps it's not entirely portable in it's solution, but certainly there are plenty of applications that do things like storing a configuration file in the installation directory.

    Of course, if it's just a case of "using the current directory", then robwhit is correct - just don't start the path with any disk or backslash, e.g. "foo.txt" or "data\foo.txt" would be valid "local" filenames/paths in the current directory (assuming there is a "data" directory in the current directory).

    --
    Mats

  6. #6
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Lol, yeah my bad. I must have been a bit confused there.

  7. #7
    Registered User
    Join Date
    Sep 2006
    Posts
    230
    Thanks everyone.

    Yes, I only wanted to open the file from wherever the program was executed from. I don't want to know where it was executed.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. File transfer- the file sometimes not full transferred
    By shu_fei86 in forum C# Programming
    Replies: 13
    Last Post: 03-13-2009, 12:44 PM
  2. Formatting the contents of a text file
    By dagorsul in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2008, 12:36 PM
  3. Basic text file encoder
    By Abda92 in forum C Programming
    Replies: 15
    Last Post: 05-22-2007, 01:19 PM
  4. Simple File encryption
    By caroundw5h in forum C Programming
    Replies: 2
    Last Post: 10-13-2004, 10:51 PM