在C,MS Windows系统中创建临时文件

时间:2012-03-15 09:46:39

标签: c windows file temporary temp

基本上,我有一个程序给出一个4兆的压缩文件,它必须将此文件解码为未压缩的~100兆,然后将其压缩回~4兆的文件。我需要将这个中间100兆字节文件存储在驱动器的某个位置(不要将其保留在内存中)。

程序是用C语言编写的,将在MS Windows 7上执行。在解压缩时,没有保证文件夹(具有写访问权限)给予程序(源文件的文件夹可能是只读的,文件夹是目标文件可能尚未指定。)

事实证明这不是一件容易的事:

1)我已经读过一个C函数,它创建一个临时文件,当关闭或程序终止时它会消失。但是,根据我的理解,它试图在根目录中的磁盘C上创建文件,所以如果用户没有权限(普通用户不这样做),这显然会失败

2)我有一个想法,使用环境/系统变量TEMP并在那里创建一个文件,但看着一个随机的Win7 PC没有调整,我看到这个变量指向c:/ windows / temp,和该文件夹拥有“用户”的特定权利 - 也就是说,他们有权读取,执行,创建和写入文件,但不能删除它们,检查它们的属性等。这意味着,我认为,如果程序是用用户权限运行的,它将能够创建一个文件但不能删除它,因此“删除”它的唯一方法是打开文件进行写入然后关闭它,使其成为0长度文件。这也是不希望的,我不知道如何从C

查询系统变量

3)所以,基本上,我现在唯一的想法是创建一个打开文件的函数:

  • 尝试在输出目录中创建临时文件(如果可能)
  • 如果失败,尝试在输入目录
  • 中创建临时文件
  • 如果失败,尝试从系统变量
  • 在TEMP目录中创建临时文件
  • 如果失败,尝试从系统变量
  • 在TMP目录中创建临时文件

和删除功能:

  • 尝试删除()文件(通过其存储在某处的名称)
  • 如果失败,它会尝试打开文件进行写入,然后关闭它,使其成为0字节文件

有更好的想法吗?

感谢任何帮助,谢谢!

PS:程序不能使用任何外部库,如MFC等,只能内置标准C函数

2 个答案:

答案 0 :(得分:6)

GetTempPath

  

检索为临时文件指定的目录的路径。

GetTempFileName

  

为临时文件创建名称。如果是唯一的文件名   生成后,将创建一个空文件并释放其句柄;   否则,只生成一个文件名。

这两个方法为您提供了获取临时文件的位置和名称的简便方法。

UPD:MSDN上的代码示例:Creating and Using a Temporary File

答案 1 :(得分: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;
}