《UNIXLinux程序设计教程》一2.9 临时文件

2.9 临时文件

应用常常需要使用临时文件来暂存数据,例如,编译程序在编译器和汇编器之间交换编译结果就常常通过临时文件来进行。这种临时文件有两个特点:允许其他用户或进程读写并且名字必须唯一。前一特点要求将它们保存在公共目录中,以便任何用户读写,UNIX系统为此提供了一个专用的公共目录/tmp。后一特点是为了防止其他进程在相同目录中创建同名文件而引起冲突。UNIX系统给应用提供了专门的临时文件命名和临时文件创建函数,以保证临时文件名的唯一性。
唯一的文件名可以通过函数tmpnam()和tempnam()而获得:

#include <stdio.h>

char tmpnam(char s);
char tempnam(const char dir, const char *pfx);

tmpnam()返回一个合法的临时文件名,此文件名的目录由中定义的宏变量P_tmpdir指定,P_tmpdir通常就是/tmp。如果参数s不是空指针,tmpnam()存储该临时文件名于s指出的字符串中,此时s指向的字符串大小应当至少不小于宏常数L_tmpnam。若s为空指针,返回值指向的字符串是由tmpnam()静态分配的,将被下一次调用tmpnam()所覆盖。在同一个进程内,tmpnam()至多可以调用TMP_MAX次,并且每一次调用生成的临时文件名各不相同。
tempnam()的功能比tmpnam()的功能还要多一点,因此名字中多一个字母“e”。它可以指定临时文件存放的目录以及文件名的前缀。dir参数给出目录的路径,pfx参数给出文件名前缀。
tempnam()依次测试下述条件来确定目录路径名:
如果定义了环境变量TMPDIR,用它的值作为目录,即它可以覆盖dir参数。
如果dir参数指向一个合法的目录字符串,用它作为目录。
如果dir参数是空指针或者指向一个非法目录路径名,使用宏变量P_tmpdir 定义的目录。
如果P_tmpdir 定义的目录不可访问,使用实现定义的目录,通常是“/tmp”。
有许多应用喜欢以某种开头字符序列来命名临时文件名,pfx参数较适合这些应用。这个参数可以是空指针,也可以指向至多5个字符的一个字符串。
tempnam()存放文件名的存储空间是用malloc()分配的,当不再需要时,应当调用free()来释放它们。
tmpnam()和tempnam()仅仅根据系统当时的情况命名一个新的临时文件名,并不实际创建文件。创建和删除临时文件都是应用自己的事情。在获得文件名和文件被实际创建的这段时间内,其他进程有可能会创建同名文件,因此不建议用它们。
函数tmpfile()能避免这种竞争条件的出现,它在命名临时文件的同时也打开它。

#include <stdio.h>

FILE *tmpfile(void);

tmpfile()以读/写方式(w+)创建一个唯一的临时文件,并返回文件指针。该临时文件在进程结束时将自动删除。C标准没有规定文件的目录,Linux默认情况下为/tmp,否则为宏变量P_tmpdir指定的目录。
例2-10 程序2-10展示了上述三个函数的用法。它先调用tmpnam(),然后用存在和不存在的路径名分别调用tempname()来查看这两个函数生成的临时文件名。最后,调用tmpfile()创建一个临时文件并向其中写入一行数据,然后反绕这个文件将数据输出到标准输出验证这个临时文件的存在。
程序2-10 创建临时文件之例

#include "ch02.h"
int main(void)
{
   FILE *tempfp;
   char tmpname[L_tmpnam],*cp;
   char line[256];
   char *pfx = "XXXXX";
   if ((cp=tmpnam(tmpname))==NULL)  // 查看tmpnam()生成的文件名
      printf("a unique name cannot be generate by tmpnam()\n");
   else
      printf("       file name get by tmpnam(): %s\n", cp);
   /* 查看tempnam()生成的文件名 */
   cp = tempnam("./", pfx);
   printf("            by tempnam(\"./\",pfx): %s\n", cp);
   free(cp);
   cp = tempnam("/not_exist_dir/", pfx);
   printf("by tempnam(\"/not_exist_dir\",pfx): %s\n", cp);
   free(cp);
    /* 用tmpfile()创建一个临时文件 */
   if ((tempfp=tmpfile()) == NULL)
      err_exit("tmpfile error");
   printf("tmpfile() created a temporary file\n");
   /* 向临时文件写入一行数据,然后将它读出并写至标准输出进行验证 */
   fputs("One line of output\n", tempfp);
   rewind(tempfp);
   if(fgets(line, sizeof(line), tempfp) == NULL)
      err_exit("fgets error");
   fputs(line,stdout);
   exit(0);
}
时间: 2024-09-22 21:06:38

《UNIXLinux程序设计教程》一2.9 临时文件的相关文章

《UNIXLinux程序设计教程》一导读

前言 十年前,我们出版了<UNIX程序设计教程>(清华大学出版社).十年来,影响UNIX编程接口的规范和标准发生了较大变化,当时写书参照的"Single UNIX Specification 2"现在已发展到了"Single UNIX Specification 4",而若干分离独立的规范和标准,包括Single UNIX Specification,现在都已经统一在POSIX.1-2008标准之下.同时,随着Linux系统的成熟和发展,UNIX系统已不

《UNIXLinux程序设计教程》一1.2 标准

1.2 标准 UNIX变体的激增产生了许多兼容性问题,特别是各种商业UNIX变体的出现使情况变得更加复杂.系统V和BSD在许多方面不同-它们有不同且互不兼容的物理文件系统.网络机制和虚拟内存结构.这些不同中有一些限制在内核设计和实现上,但另一些出现在程序设计接口层,这导致没有一个复杂的应用程序能够不加修改地同时运行于系统V和BSD系统.另一方面,商业变体常常带有各自的增值特征,应用程序员常常搞不清它们.结果,为了保证程序在各种不同的UNIX上都能工作,程序员不得不付出极大的努力.这种情形导致了对

《UNIXLinux程序设计教程》一第1章 UNIX导论

第1章 UNIX导论UNIX是一个"历史悠久"的操作系统.在开始讲述UNIX环境程序设计方法之前,我们先回顾UNIX的诞生.成长和发展历程,介绍UNIX发展过程中出现的若干标准.回顾UNIX的发展历史,有助于我们了解它具有如此强大生命力的原因,并把握它未来的发展方向:了解UNIX的标准,可以使我们理解和区分UNIX的不同实现与版本之间的区别,并编写出可移植性更好的程序.随后,作为后继章节的基础,本章将讲述UNIX的一些基本概念,并介绍与UNIX全系统有关的一些内容,例如系统信息.系统能

《UNIXLinux程序设计教程》一1.1 UNIX简史

1.1 UNIX简史 UNIX早在MS DOS.Windows出现之前就已经诞生了,到现在已有四十多年的历史. 1.1.1 UNIX的诞生 1965年麻省理工学院的MAC课题组和通用电气公司一起启动了一个项目-开发一个新的称为Multics的多用户.交互式操作系统.Multics的目的是向大用户团体提供同时计算和存储的能力.在当时批处理系统为主流的情况下,这是一个创新的概念.此后不久,贝尔实验室的计算科学研究中心也加入了这一计划.但在1969年,这个研究组认为开发Multics需要更长的时间,于

《UNIXLinux程序设计教程》一2.8 格式I/O

2.8 格式I/O 前几节介绍的流I/O函数除了以字符或行方式进行读写外,并不对数据进行解释,但在很多时候应用都会需要对输入输出数据进行解释,因为数据在计算机内的表示和人们可读的形式是不同的.数据在计算机内是二进制形式,在计算机外部常常为正文形式.例如,十进制数12在计算机内部的32位二进制表示是:00000000000000000000000000001100.当这个数在打印机上输出或者在终端屏幕上显示时,必须转换为字符'1'和'2',它们的ASCII编码分别为00110001和0011001

《UNIXLinux程序设计教程》一3.10 思考与练习

3.10 思考与练习 打开文件时,如果希望总是创建一个新文件,应当使用什么标志?如果希望每次写出的数据都实际写到物理存储设备,应当使用什么标志? 程序3-1中,存放读写数据的缓冲区大小为1024字节.请在你的机器上指定不同大小的缓冲区来运行这个程序,仔细体会缓冲区大小对程序效率的影响. open()调用成功总是返回当前可用的编号 的描述字.对同一个文件用不同open()打开的文件描述字具有 的文件位置,由dup()重复的文件描述字具有 的文件位置. 编写一个程序打印出指定文件的文件状态标签. 用

《UNIXLinux程序设计教程》一1.4 系统库

1.4 系统库 系统库给应用程序提供编译好的标准函数和系统调用函数的目标代码,这些代码在连接时与应用程序的目标代码装配在一起形成一个完整的可执行程序.UNIX系统库由许多专门的库组成,如C标准库.数学库.线程库.实时库等.本书将要介绍的函数和系统调用基本上都包含在系统库的C标准库中,也有部分包含在线程库和实时库中. C标准库不仅包含了C标准规定的函数(不包括科学计算函数以及国际化和宽字符函数),而且包含了POSIX标准定义的大部分编程接口函数.当我们编译C源程序时,编译器会自动地连接C标准库.但

《UNIXLinux程序设计教程》一2.5 文件定位

2.5 文件定位 读写文件过程中,有时会需要读某个特定位置的内容.例如,对于那种由固定大小的记录组成并能用整数索引来引用这些记录的文件,为访问其中某个特定的记录,最快捷的方法是直接定位至该记录位置进行读写,而不必一个一个地顺序跳过之前不需要的记录.为此,我们需要能够随意定位文件的位置,即随机地读写文件的任何部分. 标准I/O库提供了如下两组对随机文件进行定位的函数,用它们可以随机地读写文件的任何部分. #include <stdio.h> long int ftell(FILE *stream

《UNIXLinux程序设计教程》一2.7 流缓冲

2.7 流缓冲 每一个流都有一个输入输出缓冲区.写入流的字符并不立即写到文件中,而是先在缓冲区中聚集为一块,然后异步地以块为单位传送到文件.类似地,从流读出的字符也不是逐个地从文件中读出,而是以块为单位从文件读到缓冲区,然后从缓冲区传送给进程.这种处理方式称为缓冲. 采用缓冲的目的是为了减少调用低级I/O函数(如read()和write())的次数,因为这些真正读写文件的函数是系统调用,它们是较费时间的操作.例如,对于存储在硬盘上的文件,当进程用read()或write()读写数据时,设备驱动程