32

I'm trying to create a temporary text file in C++ and then delete it at the end of the program. I haven't had much luck with Google.

Could you tell me which functions to use?


The answers below tell me how to create a temp file. What if I just want to create a file (tmp.txt) and then delete it? How would I do that?

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Meir
  • 12,285
  • 19
  • 58
  • 70

8 Answers8

27

Here's a complete example:

#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.
}

If you know the name of the file you want to create (and are sure it won't already exist) then you can obviously just use open to open the file.

tmpnam and tmpfile should probably be avoided as they can suffer from race conditions - see man tmpfile(3) for the details.

DaveR
  • 9,540
  • 3
  • 39
  • 58
  • 2
    The Linux man page for mkstemp(3) says that the last 6 characters in filename must be XXXXXX. See http://www.kernel.org/doc/man-pages/online/pages/man3/mkstemp.3.html – jfs Jun 20 '09 at 23:52
  • Hmm, the OS X manpage for mkstemp says you can have a variable number of XXXs. however in the interests of clarity (and 'cos most people are probably using Linux) I've changed the above example. – DaveR Jun 21 '09 at 10:27
  • Actually it's mktemp and tmpnam that suffer from the race conditions you mention, not tmpfile. tmpfile returns the a C file handle, so you won't get a C++ stream, but you don't get a race condition either. I think the man pages you want to reference above are for tmpname(3) http://www.kernel.org/doc/man-pages/online/pages/man3/tmpnam.3.html and mktemp http://www.kernel.org/doc/man-pages/online/pages/man3/mktemp.3.html – Zach Burlingame May 19 '11 at 12:36
25

Maybe this will help

FILE * tmpfile ( void );

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

Open a temporary file

Creates a temporary binary file, open for update (wb+ mode -- see fopen for details). The filename is guaranteed to be different from any other existing file. The temporary file created is automatically deleted when the stream is closed (fclose) or when the program terminates normally.

See also

char * tmpnam ( char * str );

Generate temporary filename

A string containing a filename different from any existing file is generated. This string can be used to create a temporary file without overwriting any other existing file.

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

Tom
  • 43,810
  • 29
  • 138
  • 169
  • 5
    It is worth mentioning that there might be issues with tmpfile() and tmpnam() in some contexts e.g., http://www.codeproject.com/KB/web-security/TemporaryFileSecurity.aspx – jfs Jun 20 '09 at 23:06
  • 4
    Tmpfile, of course, has the problem of returning a C file handle, not a c++ stream. – rlbond Jun 21 '09 at 00:43
  • 2
    @rlbond: Indeed, thats why I included tmpnam. – Tom Jun 21 '09 at 00:44
  • 4
    it's very important to note that tmpnam() is not to be used. its man page says: "Never use this function. Use mkstemp(3) or tmpfile(3) instead." – markgalassi Apr 16 '15 at 14:28
  • Where exactly is the temporary file created? – Ryuu May 04 '18 at 09:05
  • The problem is, the second one is considered unsafe and gives you a warning, and the first one you can't get the name of and delete after use. – einpoklum Oct 02 '20 at 14:26
  • tmpnam, while part of the POSIX standard, is deprecated, and should be discouraged. See [this SO question](https://stackoverflow.com/q/35188145/1593077). – einpoklum Feb 10 '21 at 11:23
6

This may be a little off-topic because the author wanted to create a tmp.txt and delete it after using it, but that is trivial - you can simple open() it and delete it (using boost::filesystem of course).

mkstemp() is UNIX-based. With Windows you use GetTempFileName() and GetTempPath() to generate a path to a temp file. Sample code from MSDN:

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

Vector Maniac
  • 95
  • 1
  • 3
6

On Linux (starting with kernel 3.11), there's flag to open(2) O_TMPFILE that creates a temporary file that doesn't have a name (i.e. it doesn't show up in the filesystem). This has a few interesting features:

  • No worries about unique names, it's just an inode, there is no name.
  • No race conditions during creation (e.g. symlink attacks).
  • No stray files if your app crashes, it's always automatically deleted.
TheAmigo
  • 1,032
  • 1
  • 10
  • 29
  • 2
    Minimal runnable example: https://stackoverflow.com/questions/4508998/what-is-an-anonymous-inode-in-linux/44388030#44388030 I wonder if glibc can use that to implement `tmpfile`, but lazy to check now. – Ciro Santilli OurBigBook.com Oct 18 '19 at 16:49
3

I wonder why most of you guys showed him the C way of doing it instead of the C++ way.
Here's fstream.
Try that, deleting a file is OS depended but you can use boost.filesystem to make things easy for you.

the_drow
  • 18,571
  • 25
  • 126
  • 193
  • 4
    That's probably because the OP asked for a temporary file, and there are no standard C++ mechanisms for creating a unique filename. There is nothing in libstdc++ or boost that truly replaces mkstemp(). – Tom Jun 20 '09 at 22:34
2

If you need a named file (for example, so you can pass the name to another process, perhaps a compiler or editor), then register a cleanup function that removes the file with atexit(). You can use either C++ <iostream> or C FILE * (<cstdio>) to create the file. The not completely standard but widely available mkstemp() function creates a file and tells you its name as well as returning a file descriptor (a third I/O mechanism); you could use the fdopen() function to convert the file descriptor into a FILE *.

If you don't need a named file a C-style FILE * is OK, then look at tmpfile() as suggested by @Tom.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

A clean, portable and non-deprecated way of creating a temporary file is provided by Boost:

auto temporary_file = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
0

Well, assuming you have been successful in creating the temporary file, you can use the remove function to delete it.

The function is declared in stdio.h -

#include <stdio.h>

int remove(const char *pathname);

For example, if you want to delete a file named myfile.txt the code will be

#include<stdio.h>

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

I hope by now, you already know how to create the temp file, so this should resolve your query. Hope it helps.

Elitecoder
  • 170
  • 1
  • 13