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

7
基本上,我有一个程序,它会得到一个4兆压缩文件,需要将其解码成未压缩的大约100兆文件,然后再将其压缩成大约4兆的文件。我需要在硬盘上存储这个中间的100兆文件(不想将其存储在内存中)。
该程序是用C语言编写的,将在MS Windows 7上执行。在解压时,程序没有保证给定具有写访问权限的文件夹(源文件夹可能只读,目标文件夹可能尚未指定)。
这被证明不是一项容易的任务:
1)我已经了解了一个创建临时文件的C函数,当关闭或终止程序时,该文件将消失。但是,从我的理解来看,它试图在磁盘C上的根目录中创建文件,因此如果用户没有权限(普通用户没有权限),这显然会失败。
2)我曾经想过使用环境/系统变量TEMP并在那里创建一个文件,但是在查看一个未调整的随机Win7 PC时,我发现该变量指向c:/windows/temp,并且该文件夹对“用户”具有特定的权限-也就是说,他们有权读取、执行、创建和写入文件,但不能删除文件、检查其属性等。这意味着,我认为,如果程序以用户权限运行,则将能够创建文件但无法删除它,因此“删除”它的唯一方法将是打开文件进行写入,然后关闭它,使其成为0长度文件。这也是不希望发生的事情,我不知道如何从C中查询系统变量。
3)因此,基本上我现在唯一的想法是编写一个打开文件的函数:
- 尝试在输出目录中创建临时文件(如果可能) - 如果失败,请尝试在输入目录中创建临时文件 - 如果失败,请尝试在系统变量TEMP的临时目录中创建临时文件 - 如果失败,请尝试在系统变量TMP的临时目录中创建临时文件
以及一个删除函数:
- 尝试remove()该文件(通过存储在某个地方的名称) - 如果失败,则尝试打开该文件进行写入,然后关闭它,使其成为0字节文件
有更好的想法吗?
任何帮助都将不胜感激,谢谢!
PS:程序不能使用任何外部库,如MFC或其他东西,只能使用内置的标准C函数。
2个回答

6

GetTempPath

获取用于存放临时文件的目录路径。

GetTempFileName

创建一个临时文件名。如果生成唯一的文件名,则会创建一个空文件并释放其句柄;否则,仅生成文件名。

这两个函数提供了一种简单的方法来获取临时文件的位置和名称。

更新:MSDN上有代码示例:创建和使用临时文件


这是 .net 框架吗?还是我弄错了?您能否给我一个使用它们创建 FILE* 对象的代码示例? - Istrebitel
这是Windows API,文件管理函数,使用C或C++编写。获取环境变量值实际上比答案中提到的要“重”,如果需要,GetTempPath本身将查找环境变量。 - Roman R.
MSDN有一个很好的函数示例代码,http://msdn.microsoft.com/en-us/library/windows/desktop/aa363875%28v=vs.85%29.aspx,带有描述性注释。 - Roman R.
@Istrebitel 既然这是 Windows API,这些函数将在任何 Windows 编译器上工作。它们在 Windows 计算机之间完全可移植。 - Lundin
是的,谢谢,我现在明白了。然而,GetTempPath所做的只是获取环境变量(按特定顺序三个)。它不会检查您是否有写入目录的权限。因此,在某种程度上它确实有帮助,但并不能解决问题。难道没有一种方法可以获取到用户临时文件夹的路径吗?就像Audacity/7zip等程序用于暂存文件的那个路径?这类似于appdata/roaming/temp吗?可以安全地假设任何Windows 7用户都具有对其用户临时文件夹中的appdata漫游文件夹的写入/删除权限吗? - Istrebitel
显示剩余2条评论

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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接