ISO C標(biāo)準(zhǔn)I/O庫(kù)提供了兩個(gè)函數(shù)以幫助創(chuàng)建臨時(shí)文件。
#include <stdio.h>char *tmpnam( char *ptr );返回值:指向唯一路徑名的指針FILE *tmpfile( void );返回值:若成功則返回文件指針,若出錯(cuò)則返回NULL
若ptr是NULL,則所產(chǎn)生的路徑名存放在一個(gè)靜態(tài)區(qū)中,指向該靜態(tài)區(qū)的指針作為函數(shù)值返回。下一次調(diào)用tmpnam時(shí),會(huì)重寫該靜態(tài)區(qū)(這意味著,如果我們調(diào)用此函數(shù)多次,而且想保存路徑名,則我們應(yīng)該保存該路徑名的副本,而不是指針的副本)。如若ptr不是NULL,則認(rèn)為它指向長(zhǎng)度至少是L_tmpnam個(gè)字符的數(shù)組(常量L_tmpnam定義在頭文件<stdio.h>中)。所產(chǎn)生的路徑名存放在該數(shù)組中,ptr也作為函數(shù)值返回。
tmpfile創(chuàng)建一個(gè)臨時(shí)二進(jìn)制文件(類型wb+),在關(guān)閉該文件或程序結(jié)束時(shí)將自動(dòng)刪除這種文件。注意,UNIX對(duì)二進(jìn)制文件不作特殊區(qū)分。
程序清單5-4 tmpnam和tmpfile函數(shù)實(shí)例
[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);}
執(zhí)行程序:
[root@localhost apue]# ./prog5-4/tmp/fileNu68ZQ/tmp/fileaKBqgEone line fo output
不要被上面的實(shí)例程序所迷惑,并不是說(shuō)必須先用tmpnam產(chǎn)生一個(gè)路徑名,然后再調(diào)用tmpfile創(chuàng)建臨時(shí)文件。tmpfile單獨(dú)使用即可創(chuàng)建臨時(shí)文件。
tmpfile函數(shù)經(jīng)常使用的標(biāo)準(zhǔn)UNIX技術(shù)是先調(diào)用tmpnam產(chǎn)生一個(gè)唯一的路徑名,然后,用該路徑名創(chuàng)建一個(gè)文件,并立即unlink它。
Single UNIX Specification為處理臨時(shí)文件定義了另外兩個(gè)函數(shù),它們是XSI的擴(kuò)展部分。其中第一個(gè)是tempnam函數(shù)。
#include <stdio.h>char *tempnam( const char *directory, const char *prefix );返回值:指向唯一路徑名的指針
tempnam是tmpnam的一個(gè)變體,它允許調(diào)用者為所產(chǎn)生的路徑名指定目錄和前綴。對(duì)于目錄有4種不同的選擇,按下列順序判斷其條件是否為真,并且使用第一個(gè)為真的作為目錄:
(1)如果定義了環(huán)境變量TMPDIR,則用其作為目錄。
(2)如果參數(shù)directory非NULL,則用其作為目錄。
(3)將<stdio.h>中的字符串P_tmpdir用作目錄。
(4)將本地目錄(通常是/tmp)用作目錄。
如果prefix非NULL,則它應(yīng)該是最多包含5個(gè)字符的字符串,用其作為文件名的頭幾個(gè)字符。
該函數(shù)調(diào)用malloc函數(shù)分配動(dòng)態(tài)存儲(chǔ)區(qū),用其存放所構(gòu)造的路徑名。.當(dāng)不再使用此路徑名時(shí)就可釋放此存儲(chǔ)區(qū)。
程序清單5-5 演示tempnam函數(shù)
[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);}
注意,如果命令行參數(shù)(目錄或前綴)中的任一個(gè)以空白開始,則將其作為null指針傳送給該函數(shù)。下面顯示使用該程序的各種方式。
[root@localhost apue]# ./prog5-5 /home/zhu TEMP 指定目錄和前綴/home/zhu/TEMPd18A3w[root@localhost apue]# ./prog5-5 " " PFX 使用默認(rèn)目錄:P_tmpdir/tmp/PFXj8BpNK[root@localhost apue]# TMPDIR=/var/tmp ./prog5-5 /usr/tmp " " 使用環(huán)境變量:無(wú)前綴/var/tmp/fileMpGbXZ[root@localhost apue]# TMPDIR=/no/such/dir ./prog5-5 /home/zhu/test QQQ/home/zhu/test/QQQaLZExQ 忽略無(wú)效環(huán)境目錄
上述選擇目錄名的四個(gè)步驟按序執(zhí)行,該函數(shù)也檢查相應(yīng)的目錄名是否有意義。如果該目錄并不存在(例如/no/such/dir),則跳過(guò)這一步,試探對(duì)目錄名的下一次選擇。
XSI定義的第二個(gè)函數(shù)是mkstemp。它類似于tmpfile,但是該函數(shù)返回的不是文件指針,而是臨時(shí)文件的打開文件描述符。
#include <stdio.h>int mkstemp( char *template );返回值:若成功則返回文件描述符,若出錯(cuò)則返回-1
它所返回的文件描述符可用于讀、寫文件。臨時(shí)文件的名字是用template字符串參數(shù)選擇的。該字符串是一個(gè)路徑名,其最后6個(gè)字符設(shè)置為XXXXXX。該函數(shù)用于不同字符代換XXXXXX,以創(chuàng)建一路徑名。如若mkstemp成功返回,它就會(huì)修改template字符串以反映臨時(shí)文件的名字。
與tmpfile不同的是,mkstemp創(chuàng)建的臨時(shí)文件不會(huì)自動(dòng)刪除。如若想從文件系統(tǒng)名字空間中刪除該文件,則我們需要自行unlink它。
使用tmpnam和tempnam的一個(gè)不足之處是:在返回唯一路徑名和應(yīng)用程序用該路徑名創(chuàng)建文件之間有一個(gè)時(shí)間窗口。在該事件窗口期間,另一個(gè)進(jìn)程可能創(chuàng)建一個(gè)同名文件。tmpfile和mkstemp函數(shù)則不會(huì)產(chǎn)生此種問(wèn)題,可以使用它們代替tmpnam和tempnam。
mktemp函數(shù)類似于mkstemp,只不過(guò)mktemp只構(gòu)建一個(gè)適用于臨時(shí)文件的名字,它沒有創(chuàng)建一個(gè)文件,所以它也有與tmpnam和tempnam相同的不足之處。mktemp函數(shù)在Single UNIX Specification中被標(biāo)記為遺留接口。Single UNIX Specification的未來(lái)版本可能將遺留接口全部刪除,因此應(yīng)當(dāng)避免使用它。
本篇博文內(nèi)容摘自《UNIX環(huán)境高級(jí)編程》(第二版),僅作個(gè)人學(xué)習(xí)記錄所用。關(guān)于本書的更多內(nèi)容可參考:http://www.apuebook.com/。
新聞熱點(diǎn)
疑難解答
圖片精選