ISO C標準I/O庫提供了兩個函數以幫助創建臨時文件。
#include <stdio.h>char *tmpnam( char *ptr );返回值:指向唯一路徑名的指針FILE *tmpfile( void );返回值:若成功則返回文件指針,若出錯則返回NULL
若ptr是NULL,則所產生的路徑名存放在一個靜態區中,指向該靜態區的指針作為函數值返回。下一次調用tmpnam時,會重寫該靜態區(這意味著,如果我們調用此函數多次,而且想保存路徑名,則我們應該保存該路徑名的副本,而不是指針的副本)。如若ptr不是NULL,則認為它指向長度至少是L_tmpnam個字符的數組(常量L_tmpnam定義在頭文件<stdio.h>中)。所產生的路徑名存放在該數組中,ptr也作為函數值返回。
tmpfile創建一個臨時二進制文件(類型wb+),在關閉該文件或程序結束時將自動刪除這種文件。注意,UNIX對二進制文件不作特殊區分。
程序清單5-4 tmpnam和tmpfile函數實例
[root@localhost apue]# cat PRog5-4.c#include "apue.h"intmain(void){ char name[L_tmpnam], line[MAXLINE]; FILE *fp; printf("%s/n", tmpnam(NULL)); /* first tmp name */ tmpnam(name); /* second tmp name */ printf("%s/n", name ); if((fp = tmpfile()) == NULL) /* create temp file */ err_sys("tmpfile error"); fputs("one line fo output /n", fp ); /* write to temp file */ rewind(fp); /* then read it back */ if(fgets(line, sizeof(line), fp) == NULL) err_sys("fgets error"); fputs(line, stdout); /* print the line we wrote */ exit(0);}
執行程序:
[root@localhost apue]# ./prog5-4/tmp/fileNu68ZQ/tmp/fileaKBqgEone line fo output
不要被上面的實例程序所迷惑,并不是說必須先用tmpnam產生一個路徑名,然后再調用tmpfile創建臨時文件。tmpfile單獨使用即可創建臨時文件。
tmpfile函數經常使用的標準UNIX技術是先調用tmpnam產生一個唯一的路徑名,然后,用該路徑名創建一個文件,并立即unlink它。
Single UNIX Specification為處理臨時文件定義了另外兩個函數,它們是XSI的擴展部分。其中第一個是tempnam函數。
#include <stdio.h>char *tempnam( const char *directory, const char *prefix );返回值:指向唯一路徑名的指針
tempnam是tmpnam的一個變體,它允許調用者為所產生的路徑名指定目錄和前綴。對于目錄有4種不同的選擇,按下列順序判斷其條件是否為真,并且使用第一個為真的作為目錄:
(1)如果定義了環境變量TMPDIR,則用其作為目錄。
(2)如果參數directory非NULL,則用其作為目錄。
(3)將<stdio.h>中的字符串P_tmpdir用作目錄。
(4)將本地目錄(通常是/tmp)用作目錄。
如果prefix非NULL,則它應該是最多包含5個字符的字符串,用其作為文件名的頭幾個字符。
該函數調用malloc函數分配動態存儲區,用其存放所構造的路徑名。.當不再使用此路徑名時就可釋放此存儲區。
程序清單5-5 演示tempnam函數
[root@localhost apue]# cat prog5-5.c#include "apue.h"intmain(int argc, char *argv[]){ if(argc != 3) err_quit("usage: prog5-5 <directory> <prefix>"); printf("%s/n", tempnam(argv[1][0] != ' ' ? argv[1] : NULL, argv[2][0] != ' ' ? argv[2] : NULL)); exit(0);}
注意,如果命令行參數(目錄或前綴)中的任一個以空白開始,則將其作為null指針傳送給該函數。下面顯示使用該程序的各種方式。
[root@localhost apue]# ./prog5-5 /home/zhu TEMP 指定目錄和前綴/home/zhu/TEMPd18A3w[root@localhost apue]# ./prog5-5 " " PFX 使用默認目錄:P_tmpdir/tmp/PFXj8BpNK[root@localhost apue]# TMPDIR=/var/tmp ./prog5-5 /usr/tmp " " 使用環境變量:無前綴/var/tmp/fileMpGbXZ[root@localhost apue]# TMPDIR=/no/such/dir ./prog5-5 /home/zhu/test QQQ/home/zhu/test/QQQaLZExQ 忽略無效環境目錄
上述選擇目錄名的四個步驟按序執行,該函數也檢查相應的目錄名是否有意義。如果該目錄并不存在(例如/no/such/dir),則跳過這一步,試探對目錄名的下一次選擇。
XSI定義的第二個函數是mkstemp。它類似于tmpfile,但是該函數返回的不是文件指針,而是臨時文件的打開文件描述符。
#include <stdio.h>int mkstemp( char *template );返回值:若成功則返回文件描述符,若出錯則返回-1
它所返回的文件描述符可用于讀、寫文件。臨時文件的名字是用template字符串參數選擇的。該字符串是一個路徑名,其最后6個字符設置為XXXXXX。該函數用于不同字符代換XXXXXX,以創建一路徑名。如若mkstemp成功返回,它就會修改template字符串以反映臨時文件的名字。
與tmpfile不同的是,mkstemp創建的臨時文件不會自動刪除。如若想從文件系統名字空間中刪除該文件,則我們需要自行unlink它。
使用tmpnam和tempnam的一個不足之處是:在返回唯一路徑名和應用程序用該路徑名創建文件之間有一個時間窗口。在該事件窗口期間,另一個進程可能創建一個同名文件。tmpfile和mkstemp函數則不會產生此種問題,可以使用它們代替tmpnam和tempnam。
mktemp函數類似于mkstemp,只不過mktemp只構建一個適用于臨時文件的名字,它沒有創建一個文件,所以它也有與tmpnam和tempnam相同的不足之處。mktemp函數在Single UNIX Specification中被標記為遺留接口。Single UNIX Specification的未來版本可能將遺留接口全部刪除,因此應當避免使用它。
本篇博文內容摘自《UNIX環境高級編程》(第二版),僅作個人學習記錄所用。關于本書的更多內容可參考:http://www.apuebook.com/。
新聞熱點
疑難解答