【问题标题】:Create temporary file in C, MS Windows system在 C、MS Windows 系统中创建临时文件
【发布时间】:2012-03-31 19:34:50
【问题描述】:

基本上,我有一个程序,它有一个 4 meg 的压缩文件,它必须将此文件解码为未压缩的 ~ 100 meg,然后将其压缩回 ~4 meg 文件。我需要将这个 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 函数

【问题讨论】:

    标签: c windows file temporary temp


    【解决方案1】:
    #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;
    }
    

    【讨论】:

      【解决方案2】:

      GetTempPath

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

      GetTempFileName

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

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

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

      【讨论】:

      • 这是.net框架?还是我弄错了?您能给我一个使用这些创建 FILE* 对象的代码示例吗?
      • 这是 Windows API、文件管理功能、C 或 C++。与答案中提到的相比,获取环境变量值实际上是一个“更重”的功能。如果需要,GetTempPath 会自行查找环境变量。
      • MSDN 有一个很好的函数示例代码 msdn.microsoft.com/en-us/library/windows/desktop/… 带有描述性注释。
      • @Istrebitel 因为它是 Windows API,所以这些函数可以在任何 Windows 编译器上运行。它们完全可以在 Windows 计算机之间移植。
      • 是的,谢谢你,我现在明白了。但是,GetTempPath 所做的只是获取环境变量(三个,按特定顺序)。它不检查您是否具有对该目录的写入权限。所以,它在某种程度上确实有帮助,但不能解决问题。有没有办法获得用户临时文件夹的路径,像 Audacity/7zip/etc 这样的程序用来临时存储文件的路径?它类似于 appdata/roaming/temp 吗?可以安全地假设任何 Windows 7 用户在 appdata 漫游中都拥有对其用户临时文件夹的写入/删除权限?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-02
      • 1970-01-01
      • 2010-11-02
      • 2013-04-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多