7

Basically, i have a program that is given a 4 meg compressed file, it has to decode this file into uncompressed ~ 100 meg, then compress it back into ~4 meg file. I need to store this intermediate 100 meg file somewhere on the drive (dont want to keep it in memory).

Program is written in C and will be executed on MS Windows 7. At the moment of uncompressing, no guaranteed folder (with write access) is given to the program (folder with source file might be read only and folder with target file might be not yet specified).

This has proven to be not an easy task:

1) I have read about a C function that creates a temp file that will disappear when closed or program is terminated. However, from what i understand it tries to make the file on disk C, in root directory, so this will obviously fail if user has no rights for that (which normal user doesnt)

2) I had an idea to use environmental/system variable TEMP and create a file there, BUT looking on a random Win7 PC which wasnt tweaked, i see that this variable points to c:/windows/temp, and that folder has specific rights for "users" - that is, they have rights to read, execute, create and write files, but not to delete them, check their attributes, etc. This means, i assume, that if program is ran with user privilleges, it will be able to make a file but not able to delete it, so the only way to "delete" it would be to open the file for writing and then close it, making it a 0 length file. This is also not desired, and i dont know how to query for system variables from C

3) So, basically, only idea i have right now is to make a function to open file that:

  • tries to create a temp file in the output dir, if possible
  • if failed, tries to create a temp file in input dir
  • if failed, tries to create a temp file in TEMP dir from system variable
  • if failed, tries to create a temp file in TMP dir from system variable

and a delete function that:

  • tries to remove() the file (by its name that is stored somewhere)
  • if failed, it tries to open the file for write, and close it, so it becomes a 0 byte file

Are there better ideas?

Any help is appreciated, thanks!

PS: Program must not use any external libraries like MFC or something, only built-in standart C functions

Istrebitel
  • 2,963
  • 6
  • 34
  • 49

2 Answers2

6

GetTempPath

Retrieves the path of the directory designated for temporary files.

GetTempFileName

Creates a name for a temporary file. If a unique file name is generated, an empty file is created and the handle to it is released; otherwise, only a file name is generated.

These two provide you easy way to obtain a location and name for a temporary file.

UPD: Code sample on MSDN: Creating and Using a Temporary File.

Roman R.
  • 68,205
  • 6
  • 94
  • 158
  • This is .net framework? Or am i mistaken? Could you please give me a code example of creating a FILE* object using those? – Istrebitel Mar 15 '12 at 10:06
  • This is Windows API, file management functions, C or C++. Getting environment variable value is in fact a "heavier" function as compared to mentioned in the answer. GetTempPath will itself look for environment variables, if needed. – Roman R. Mar 15 '12 at 10:09
  • MSDN has a nice sample code for the functions http://msdn.microsoft.com/en-us/library/windows/desktop/aa363875%28v=vs.85%29.aspx with descriptive comment. – Roman R. Mar 15 '12 at 10:11
  • @Istrebitel And since it is Windows API, these functions will work on any Windows compiler. They are completely portable between Windows computers. – Lundin Mar 15 '12 at 10:15
  • Yes thank you i see now. However, all GetTempPath does is gets the environmental variable (three, in specific order). It doesnt check if you have write access to the directory. So, it does help in some way, but doesnt solve the problem. Isnt there a way to get a path to user temp folder, one that programs like Audacity/7zip/etc use to store files temporarily? Its something like appdata/roaming/temp? It is safe to assume that any windows 7 user has write/delete permissions to his user temp folder in appdata roaming? – Istrebitel Mar 15 '12 at 12:38
  • It is the primary API to obtain the directory and most of the well written apps use it. Default location is indeed under AppData. – Roman R. Mar 15 '12 at 12:41
  • Ah yes i see. I mistook environmental for system variable. System variable is Windows/Temp but environmental is %USERPROFILE%\AppData\Local\Temp thats what i need. Thanks – Istrebitel Mar 15 '12 at 12:49
0
#include <windows.h>
#include <iostream>
#include <chrono>
#include <string>
#include <cstdio>
#include <chrono>

using namespace std;

int FileExists(string& filepath)
{
  DWORD dwAttrib = GetFileAttributes(filepath.c_str());
  return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
         !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}

int GetTemporaryFilePath(
    string  filePrefix,
    string  fileExt,
    string& TmpFilePath /*return*/)
{
    if (fileExt[0] == '.')
        fileExt.erase(0,1);

    char TempPath[MAX_PATH] = { 0 };

    if (!GetTempPath(MAX_PATH, TempPath))
        return -1;

    uint16_t tickint = 0;

    while(1) {
        const int nowlen = 17; char nowstr[nowlen];
        const int ticklen = 5; char tickstr[ticklen];

        // Milliseconds since 1970
        auto ms = chrono::duration_cast<chrono::milliseconds>(
            chrono::system_clock::now().time_since_epoch()
        );
        __int64 nowint = ms.count();

        snprintf(nowstr,  nowlen,  "%016" "I64" "x", nowint);
        snprintf(tickstr, ticklen, "%04x", tickint);

        TmpFilePath = string(TempPath)
                    + filePrefix
                    + "."   + string(nowstr)
                    + "."   + string(tickstr)
                    + "."   + fileExt;

        if (!FileExists(TmpFilePath)) {
            //Touch File
            FILE* w = fopen(TmpFilePath.c_str(), "w");
            fclose(w);
            break;
        }
        tickint++;
     }

     return 0;
}

int main()
{
    string TmpFilePath;
    GetTemporaryFilePath("MyFile", ".txt", TmpFilePath);
    cout << "TmpFilePath: " << TmpFilePath << endl;
    return 0;
}
Bimo
  • 5,987
  • 2
  • 39
  • 61