如何在C++中创建临时文本文件?

32
我正在尝试在C++中创建一个临时文本文件,并在程序结束时删除它。我在谷歌上没有找到太多有用的信息。请问应该使用哪些函数?
下面的答案告诉了我如何创建一个临时文件。如果我只想创建一个文件(tmp.txt)然后删除它,该怎么做?

然后在文件末尾删除已翻译的文本? - Tom
http://www.cplusplus.com/doc/tutorial/files/ - g06lin
是的。临时文件只包含临时数据。输出将写入现有的 output.txt 文件中。 - Meir
对于目录:https://dev59.com/b3A75IYBdhLWcg3wSm64#58454949 - Ciro Santilli OurBigBook.com
8个回答

27

以下是一个完整的示例:

#include <unistd.h>

int main(void) {
  char filename[] = "/tmp/mytemp.XXXXXX"; // template for our file.        
  int fd = mkstemp(filename);    // Creates and opens a new temp file r/w.
                                 // Xs are replaced with a unique number.
  if (fd == -1) return 1;        // Check we managed to open the file.
  write(fd, "abc", 4);           // note 4 bytes total: abc terminating '\0'
  /* ...
     do whatever else you want.
     ... */
  close(fd);
  unlink(filename);              // Delete the temporary file.
}

如果您知道要创建的文件名(并且确定它不存在),那么您可以显然使用open打开该文件。

tmpnamtmpfile 应该避免使用,因为它们可能会受到竞态条件的影响 - 请参阅 man tmpfile(3)获取详细信息。


2
Linux中mkstemp(3)的man页面指出,文件名中的最后6个字符必须是XXXXXX。请参见http://www.kernel.org/doc/man-pages/online/pages/man3/mkstemp.3.html。 - jfs
嗯,OS X的mkstemp手册说你可以有可变数量的XXX。 然而出于清晰和大多数人可能正在使用Linux的考虑,我已更改上面的示例。 - DaveR
实际上,受到你所提到的竞态条件影响的是 mktemp 和 tmpnam,而不是 tmpfile。tmpfile 返回一个 C 文件句柄,因此你不会得到 C++ 流,但也不会遇到竞态条件。我认为你想引用的 man 页面是 tmpname(3) http://www.kernel.org/doc/man-pages/online/pages/man3/tmpnam.3.html 和 mktemp http://www.kernel.org/doc/man-pages/online/pages/man3/mktemp.3.html。 - Zach Burlingame

25

也许这可以帮助你

FILE * tmpfile ( void );

http://www.cplusplus.com/reference/clibrary/cstdio/tmpfile/

打开一个临时文件

创建一个临时二进制文件,以更新模式(wb+模式--参见fopen的详细信息)打开。文件名保证与任何其他现有文件不同。当流关闭(fclose)或程序正常终止时,自动删除所创建的临时文件。

另请参阅

char * tmpnam ( char * str );

生成临时文件名

生成一个包含文件名的字符串,该文件名与任何现有文件不同。可以使用此字符串创建临时文件,而不会覆盖其他现有文件。

http://www.cplusplus.com/reference/clibrary/cstdio/tmpnam/


6
值得一提的是,在某些情况下,例如http://www.codeproject.com/KB/web-security/TemporaryFileSecurity.aspx中可能存在tmpfile()和tmpnam()问题。 - jfs
4
当然,Tmpfile存在一个问题,它返回的是C文件句柄而不是C++流。 - rlbond
2
@rlbond:确实,这就是我包含tmpnam的原因。 - Tom
4
非常重要的是要注意,不应使用tmpnam()函数。它的手册页面上说:“永远不要使用此函数。请改用mkstemp(3)或tmpfile(3)。” - markgalassi
tmpnam虽然是POSIX标准的一部分,但已被弃用,应该避免使用。请参见此SO问题 - einpoklum
显示剩余2条评论

6
在Linux上(从内核3.11开始),有一个标志可以使用open(2)的O_TMPFILE来创建一个没有名称的临时文件(即它不会在文件系统中显示)。 这有一些有趣的特点:
  • 毋需担心唯一名称,它只是一个inode,没有名称。
  • 在创建期间没有竞争条件(例如符号链接攻击)。
  • 如果您的应用程序崩溃,也不会留下杂散文件,因为它总是被自动删除。

2
最小可运行示例:https://dev59.com/nm855IYBdhLWcg3wJgxy#44388030 我想知道glibc是否可以使用它来实现tmpfile,但现在懒得检查。 - Ciro Santilli OurBigBook.com

6
这可能有点偏题,因为作者想要创建一个tmp.txt并在使用后删除它,但这很琐碎——你可以简单地使用open()打开它并删除它(当然要使用boost::filesystem)。
mkstemp()是基于UNIX的。对于Windows,您可以使用GetTempFileName()和GetTempPath()生成临时文件的路径。以下是来自MSDN的示例代码:

http://msdn.microsoft.com/en-us/library/aa363875%28VS.85%29.aspx


3
我想知道为什么大多数人向他展示了C的方法,而不是C++的方法。
这里有 fstream
试试这个,删除文件取决于操作系统,但你可以使用boost.filesystem使事情变得容易。

4
可能是因为原帖作者要求创建一个临时文件,而C++并没有标准机制来创建唯一的文件名。在libstdc++或boost中没有任何东西能真正取代mkstemp()函数。 - Tom

2
如果您需要一个命名的文件(例如,这样您可以将名称传递给另一个进程,可能是编译器或编辑器),则注册一个清理函数,使用 atexit() 删除该文件。您可以使用C++的<iostream>或C的FILE * (<cstdio>)来创建文件。不完全标准但广泛可用的mkstemp()函数创建一个文件并告诉您其名称以及返回一个文件描述符(第三个I/O机制);您可以使用fdopen()函数将文件描述符转换为FILE *
如果您不需要命名文件,则可以使用C风格的FILE *,然后查看@Tom建议的tmpfile()

1
提供了一种干净、便携且未过时的创建临时文件的方法,由 Boost 提供:
auto temporary_file = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();

0

假设您已成功创建了临时文件,那么您可以使用remove函数来删除它。

该函数在stdio.h中声明 -

#include <stdio.h>

int remove(const char *pathname);

例如,如果您想要删除名为myfile.txt的文件,则代码将是:
#include<stdio.h>

int main()
{
  if(remove("myfile.txt") == -1)
  {
    fprintf(stderr,"Remove failed");
    exit(EXIT_FAILURE);
  }
  exit(EXIT_SUCCESS);
}

希望现在你已经知道如何创建临时文件,这应该解决了你的问题。 希望能有所帮助。


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