(二) Unix/Linux 文件编程

文件和目录

stat()/fstat()/lstat() 成功返回0,出错返回-1.

获取与文件目录有关的信息结构,fstat参数为已打开的文件描述符,而lstat

可以处理符号链接,当文件是一个符号链接时,返回的是符号链接的信息而不是引用文件的信息(否则在处理目录时可能引起死循环)。

信息结构struct stat 的大部分信息都取自i节点,文件名和i节点存放于目录项。具体信息一般有文件类型、i节点号、文件所有者、文件大小、文件时间、文件链接数等。

目录相关的函数:

mkdir() - 新建一个空目录(mkdir命令)

        rmdir()-  删除一个空间目录(rmdir命令)

     chdir()  - 切换当前的目录(cd命令)

getcwd - 获得当前目录的绝对路径形式(双返回)但不打印

实现读取目录中的内容:

opendir() - 打开一个目录

        readdir()- 读目录的内容(子项,子文件或子目录)

       closedir()- 关闭已经打开的目录(不关闭也行)

读某个目录内容(子项)的步骤:

1.       opendir()返回目录指针

2.       循环调用readdir(),逐一读取每个子项。(忽略“.”和“..”)

3.       closedir()关闭目录,这步也可以省略。

 

文件i/o

Linux系统中一切皆文件,目录、内存、各种硬件设备都可以当作文件操作。

/dev/tty - 键盘,也代表 显示器

/dev/null - 空设备,就是用于清空东西的 虚拟设备

cat /dev/null > a.txt   -  清空a.txt

ls -l > /dev/null   -  执行命令,但不做任何的显示

 

系统调用方式访问文件

每个进程在进程表中维持一个记录项,其中包含打开的文件描述符表,文件描述符是一个非负整数,每个描述符对应一张文件表。

0 1 2 已经被系统预先使用,代表标准输入、标准输出和标准错误。文件描述符从3开始,最大到OPEN_MAX。文件描述符可以循环利用,close()以后就可以再次使用。

 int creat ( constchar *filename ,mode_t mode )

常见创建模式:

S_IRUSR 可读;S_IWUSR可写;S_IXUSR 可执行 ; S_IRWXU可读写执行

除了使用上述宏以外还可以直接使用数字来表示文件的访问权限

例如:creat (filename ,0755);

 

int open (constchar *path ,int flags, mode_t mode )

当打开文件不存在时使用O_CREAT标志,并使用第三个参数。

常见打开标志:

       O_RDONLY O_WRONLY  O_RDWR : 打开的权限。

       O_CREAT : 创建标识,文件存在就打开,不存在就新建

       O_TRUNC : 打开文件时自动清空文件(open是清空)

       O_EXCL : 文件不存在新建,存在就返回-1代表出错

上面两个一般都是和O_CREAT结合使用

       O_APPEND : 采用追加的方式打开文件,一般用于写。

close()函数用于关闭文件描述符,不一定关闭文件表。close()其实就是在描述符总表中移除对应关系,文件表的计数会减1,当文件表的计数到0时,文件表就可以被回收。

 

读写函数:

       int read(int fd,void* buf,size_t count)

       int write(int fd,void* buf,size_t length)

参数count是buf的真实大小,不一定读满

参数length不是buf的大小,而是 写入数据的大小

read() 返回 正数就是真实读到的字节数,0代表读完了,-1代表出错。

write()返回正数 就是真实写入的字节数,0代表什么都没写,-1代表出错。

 

系统有一个权限屏蔽字,默认权限屏蔽是屏蔽其他用户的写权限,权限屏蔽字可以修改。

mode_t  umask(mode_t cmask)

传入新的屏蔽字,返回旧的屏蔽字。

 

off_t lseek (intfd ,off_t offset ,int whence )  文件定位,即文件偏移量。

返回: 移动以后的位置和文件头的距离,失败返回 -1 。

基准点whence使用下述值:

SEEK_SET相对文件开头;SEEK_CUR文件读写指针的当前位置;SEEK_END末尾

offset可取负值例如:lseek( fd,-5,SEEK_CUR)

使用VIM时都会在文件末尾加一个\n,因此文件大小会多一个字节。

 

int access (constchar *pathname ,int mode )

mode:R_OK可读,W_OK可写,X_OK可执行,F_OK文件存在

判断文件是否可以进行某种操作、文件是否存在。

内核以进程的有效用户ID和有效组ID为基础执行访问权限测试,而access函数是按实际用户ID和实际组ID来进行访问权限测试。

实际用户ID是文件的性质,有效用户ID是进程的性质。

 

dup()和dup2()  复制文件描述符

dup家族复制文件描述符时不会复制文件表,即多个描述符对应同一张文件表。

dup()是系统选择新的描述符的值(未使用的最小值)

dup2()是程序员指定新的描述符的值,如果指定的值已经被使用,会强制关闭后继续使用。

 

fcntl() 函数 - 提供一些文件控制的功能,包括:

文件描述符的复制、设置或者获取文件描述符的状态、文件锁

int fcntl(intfd,int cmd,...);

参数fd就是文件描述符,cmd是命令,...代表0-n个任意类型的参数。

返回和 cmd 的选择有关

cmd 主要包括:

1.       F_DUPFD- 复制文件描述符,需要传入第三个参数做新的描述符的值,如果这个值已经被使用,找 大于该值的未使用的最小值。

2.       F_SETFL/F_GETFL- 设置/获取 文件描述符的状态,SETFL基本用不到,因为只能修改O_APPEND;GETFL不需要第三个参数,可以获取 权限和 O_APPEND,创建标识无法获取。

3.       F_SETLK/F_SETLKW- 设置文件锁 

 

其他的一些常用函数:(f开头的对已打开的文件操作)

chmod() 和fchmod () - 修改文件的权限

chown ()、fchown()和lchown() –更改文件的用户ID和组ID

truncate()和ftruncate()  – 文件截短,即指定文件的大小。

link()和unlink()-创建硬链接和删除目录项(文件的链接计数减1,计数为0时,该文件的内容才删除,对创建的文件立即调用unlink,进程关闭该文件或终止时,文件的内容才会被删除。

remove() - 删除文件或者 空目录,功能分别与unlink和rmdir相同。

rename() - 文件或者 目录 改名。

symlink()和readlink()-创建和打开符号链接。

 

库函数访问文件

FILE *fopen (const char *filename,const char * mode )

常见打开模式:r,rb w,wb      a,ab              r+,r+b,rb+     w,w+b,wh+   a+,a+b,ab+

b用于在windows中区分二进制文件和文本文件在,linux中不区分。

 

int fclose(FILE *fp)   关闭一个流

 

Size_t fread (void *ptr, size_t size , size_t n, FILE *stream )

Size_t fwrite (const void *ptr, size_t size, size_t n, FILE *stream )

 

int fgetc(FIEL*stream) 从指定文件读取一个字符

int fputc (intc,FILE *stream )向指定文件写入一个字符

 

fscanf (FILE*stream ,char * formate[,argument ….]

从一个流中进行格式化输入

int fprintf (FILE*stream ,char *formate[,argument…])

格式化输出到一个流中

int fseek(FILE*stream ,long offset ,int whence )

文件定位

int ftell(FILE * fp)  返回当前文件位置

标C中要用fseek()+ftell()获取文件的大小。

其它常用函数

int rewind(FILE *fp) 将一个流设置到文件的起始位置。

int ferror(FILE *fp) 判断一个流是否出错。

int feof(FILE *fp) 判断是否到达文件尾(这个函数需谨慎使用)。

int fileno(FILE *fp) 文件指针转换为文件描述符。

char *tmpnam(char *ptr)

FILE *tmpfile(void) 这两个函数创建临时文件。

int fflush(FILE *fp) 强制冲洗一个流。

当流涉及终端时,通常使用行缓冲。行缓冲在缓冲区满时或者有换行符\n,冲洗缓冲区,标C不对字符进行缓冲,标准出错是不带缓冲的。

 

UC函数在用户层没有输入输出的缓冲区,而标C函数有缓冲区。UC函数写一次就访问一次内核;标C函数先放入缓冲区,等缓冲区满了再访问一次内核。但UC函数可以 由 程序员自定义缓冲区,从而大幅 提升效率。

标C可以使用以下两个函数更改和设定缓冲区大小:

void setbuf(FILE *fp,char * buf)

int setvbuf (FILE *fp,char *buf, intmode , size_t size )

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值