Linux_文件编程_第1页
Linux_文件编程_第2页
Linux_文件编程_第3页
Linux_文件编程_第4页
Linux_文件编程_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Linux 文件编程一.Linux文件结构:在linux中一切皆文件。与UNIX一样,Linux环境中的文件具有特别重要的意义,因为它们为操作系统的服务和设备提供了一个简单而统一的接口。这就意味着,通常,程序完全可以像使用文件那样使用磁盘、串行口、打印机和其他设备。Linux系统把磁盘分成为几个的partition区域,每个partition区域分成若干个Group来方便进行管理。每个group里面都有inode以及block区域。每个partition里面的inode以及block分别的都进行编号。文件系统中实际的使用的都是这些的编号。一般的,inode区域是存放文件信息的数据区域;bloc

2、k区域才是实际的存放文件实际数据的地方。Inode中存放对应文件的权限、属性、时间(atime,ctime,mtime)信息等,以及文件的实际存放区域的所有block号码。目录的inode中存放此目录的相关的权限属性等信息以及其对应的block区域的号码;目录的block数据区域中存放目录下对应的档案以及子目录的文件名以及其各自对应的inode号码。档案的inode中存放的是档案本身的权限以及属性等的信息,以及档案实际存放数据区域的block的号码;而档案的block数据区域中存放的才是档案的具体的内容数据信息。1.目录:Linux是以文件(档案)的形式进行系统管理的。而档案文件的存放需要in

3、ode以及block,档案的存放除了存储其本身包含的内容以外,它还会有一个名字和一些属性,即“管理信息”,例如文件的创建/修改 日期和它的访问权限等。这些属性被保存在文件的inode(结点)数据结构中,它是文件系统中的一个特殊的数据块,它同时还包含文件的长度和文件在磁盘上的存放位置。系统使用的是文件的inode编号,目录结构仅仅是出于方便人们使用的目的而文件命名。目录,是用来保存其他文件的结点号和名字也有其专属的inode以及block。目录文件中的每个数据项都指向某个文件的节点,删除文件名就等以删除对应的链接(ls id xxx命令用于查看xxx档案/目录,所对应的inode节点号码),你可

4、以通过使用命令ln 在不同的目录中创建指向同一个文件的链接。Linux系统中删除文件只不过是删除的其所在目录的block中的inode节点指向。而原来此档案所对应的block数据块中的内容并没有被清除。如果指向某个文件的链接数(即ls -l 命令的输出中跟在访问权限后面的那个数字)变为零,就表示该节点以及其指向的数据不再被使用,磁盘上的相应位置就会被即为可用的空间。文件被安排在目录中,目录中可能还包含子目录。这些构成了我们所熟悉的文件系统层次结构。用户(比如:project)通常会把自己的文件保存在主目录中,可能是目录/root/project,该目录可以再进一步划分为电子邮件、商业信函、工具

5、程序等子目录。许多UNIX和linux的shell命令都允许通过一个简单的符号,让用户能够进入自己的主目录,这就是波浪线符号。要想进入他人的主目录,就键入usr(加用户名)即可。如你所知,每个用户的主目录通常是一个上层目录的子目录,这个上层目录专为此目的而创建,在这个例子中它就是/root目录。2.文件和设备硬件设备在Linux操作系统中通常被表示(映射)为文件。例如:CD-ROM设备在开机引导时被加载为/dev/hdc,作为超级用户(root),你可以通过如下命令将CD-ROM驱动器挂载为一个文件:# mount -t iso9660 /dev/hdc /mnt/cdrom# cd /mnt

6、/cdrom此命令即把CD-ROM挂载为/mnt/cdrom目录下的文件结构。然后,你就可以像操作普通文件那样在CD-ROM目录中漫游,只不过该目录中的内容是只读(read-only)的。UNIX和Linux中比较重要的设备文件有三个:/dev/console /dev/tty /dev/null(1) /dev/console这个设备代表的是系统控制台。错误信息和诊断信息通常会被发送到这个设备。每个UNIX系统都会有一个指定的终端或显示屏用接收控制台消息。过去,它可能是一台专用的打印终端。在现代的工作站和Linux上,它通常是“活跃”的虚拟控制台;而在X窗口系统中,它会使屏幕上一个特殊的控制

7、台窗口。(2) /dev/tty 如果一个进程有控制终端的话,那么特殊文件/dev/tty 就是这个控制终端(键盘和显示屏,或者键盘和窗口)例如:通过cron 运行的进程就没有控制终端,所以它们不能打开/dev/tty 在能够使用该设备文件的情况下,/dev/tty允许程序直接向用户输出信息,而不管用户具体使用的是那种类型的伪终端或硬件终端。在标准输出被重定向时,这一功能非常有用。命令ls -R |more 就是一个这样的例子,more程序需要提供用户进行键盘操作之后才能显示下一页内容。注意:虽然/dev/console设备只有一个,但通过/dev/tty却能访问许多不同的物理设备(3) /d

8、ev/null这是空(null)设备。所有写向这个设备的输出都将被丢弃。而读这个设备会立刻返回一个文件尾标志,所以在cp命令里可以把它用做拷贝空文件的源文件。人们常把不需要的输出重定向到/dev/null 。创建空文件的另一方法是:使用touch <filename>命令,它的作用是改变文件的修改时间,如果指定名字不存在,就创建一个新文件,但它并不会把有内容的文件变成空文件。3.系统调用和设备驱动程序操作系统的核心部分,即内核。内核也可以理解为是一组设备驱动程序。这是一些对系统硬件进行控制的底层接口。例如:磁带机就有一个与之对应的设备驱动程序,他知道如何启动磁带,如何对它进行前后回

9、绕、如何对它进行读写等。它还知道磁带必须以固定长度的数据块为单位进行读写。因为磁带上的数据读写操作完全是线性的,所以该驱动并不能直接访问磁带上的数据块。而是必须先把它回绕到正确的位置。类似的,一个底层的硬盘设备驱动程序一次只能读写一整块硬盘扇区,但却能够直接存取硬盘上任意位置上的数据,因为硬盘是一种随机存储设备。为了向用户提供一个统一的接口,设备驱动程序封装了所有与硬件相关的特性。硬件的特有功能可通过ioctl完成。ioctl是设备驱动程序中对设备的I/O通道进行管理的函数。所谓对I/O通道进行管理,就是对设备的一些特性进行控制,例如串口的传输波特率、马达的转速等等。它的参数个数如下:int

10、ioctl(int fd, int cmd, );其中fd就是用户程序打开设备时使用open函数返回的文件标示符,cmd就是用户程序对设备的控制命令,至于后面的省略号,那是一些补充参数,一般最多一个,有或没有是和cmd的意义相关的。ioctl函数是文件结构中的一个属性分量,就是说如果你的驱动程序提供了对ioctl的支持,用户就能在用户程序中使用ioctl函数控制设备的I/O通道。/dev目录中的设备文件的用法都是一致的,它们都可以被打开、读、写和关闭。例如:用来访问普通文件的open调用同样可以用来访问一台用户终端、一台打印机设备或一台磁带机。用来访问设备驱动程序的底层函数(系统调用)包括:o

11、pen打开文件或设备read从打开的文件或设备里读数据write向文件或设备写数据close关闭文件或设备ioctl把控制信息传递给设备驱动程序系统ioctl用来提供一些与特定硬件设备有关的必要控制(与正常输入输出相反),所以它的用法随设备的不同而不同。例如:ioctl调用可以用于回绕磁带机或设置串行口的流控特性。因此,ioctl并不需要具备可移植性。此外,每个驱动程序都定义了自己的一组ioctl命令。4.库函数 在输入输出操作中,直接使用底层系统调用的问题使它们的效率非常低。为什么呢? 系统调用会影响系统的性能。与函数调用相比,系统调用的开销要大些,因为在执行系统调用时,Linux必须从用户

12、代码切换到内核代码运行,然后再返回用户代码。减少这种开销的一个好方法是,在程序中尽量减少系统调用的次数,并且让每次系统调用完成尽可能多的工作。例如:每次读写大量的数据而不是每次仅读写一个字符。硬件会对底层系统调用一次所能读写的数据块做出一定的限制。例如:磁带机通常的写操作数据块的长度为10k,所以如果卸的数据量不是10k的整数倍,磁带机还是会以10k为单位卷绕磁带,这就在磁带上留下了空隙。为了给设备和磁盘文件提供更高层的接口,与Unix一样,Linux发行版提供了一系列的标准函数库。它们是一些由函数构成的集合,你可以把它们包括在自己的程序中去处理呢些与设备和文件有关的问题。提供输出缓冲功能的标

13、准IO库就是一个这样的例子。你可以高效地写任意长度的数据块,库函数则在数据满足数据块长度要求时安排执行底层系统调用。这就极大的降低了系统调用的负面影响。库函数会有一个与之相对应的标准头文件,例如:与标准IO库对应的头文件stdio.h下图显示了Linux系统中各种文件函数与用户、设备驱动程序、内核和硬件之间的关系。5.底层文件访问每个运行中的程序被称为进程(process),它有一些与之相关联的文件描述符。这是一些小值整数,你可以通过它们访问打开的文件或设备。有多少文件描述符可用取决于系统的配置情况。当开始运行程序时,它一般会有三个已经打开的文件描述符。它们是:0:标准输入1:标准输出2:标准

14、出错二、文件IO这里提到的文件IO操作指不带缓存的IO操作,也就是说这里所提到的所有的函数的实现都是通过系统调用实现的,而不是直接对IO端口操作实现的。1.POSIX以及C库调用文件的操作主要牵涉到了如下五个动作:打开、关闭、读、写、定位。在Linux系统中,提供了两套API:<1>、一套是C标准API:fopen、fclose、fread、fwrite、fseek;<2>、一套则是POSIX定义的系统API:open、close、read、write、seek。其中POSIX定义的API是系统API,而C标准API是基于系统API的封装,并且提供了额外的缓冲的功能。因

15、此也可以把它们叫做缓冲I/O函数和非缓冲I/O函数。为什么要有增加缓冲区这个功能呢?主要是因为IO操作时,操作系统要从用户态转换为内核态(进程的运行由用户空间转去内核空间),而这个转换过程相对来说比较慢,因此可以通过缓冲的形式减少转换到内核态的次数。那么,缓冲IO函数又是如何工作的呢?当用fopen(C库API)打开文件时,除了分配文件句柄(即fd)外,还额外申请了一个缓冲区。读文件时,会首先读到缓冲区中,然后返回用户需要的部分,多余的部分仍然放在缓冲区,下次再读的时候可以直接从缓冲区中返回;写文件时,会先写到缓冲区中,等缓冲区满后再统一写到文件中。那么,我们该如何选择哪一组I/O函数呢?非缓

16、冲I/O函数(即POSIX定义的系统API),每次读写都要进内核,调一个系统调用的函数要比调一个用户空间的函数要慢很多,所以在用户空间开辟I/O缓冲区还是必要的。但是用缓冲I/O库函数要时刻注意I/O缓冲区和实际文件有可能不一致,在必要时需调用fflush()。I/O函数也用于读写设备,比如终端或网络设备。此时通常需要更快的响应,一般不使用缓冲I/O函数。*PS:严格来讲,就算是POSIX的I/O函数,仍然是有内核I/O缓冲的,所以write也不一定是直接写到文件的,也可能写到内核I/O缓冲区中,至于究竟写到了文件中还是内核缓冲区中对于进程来说是没有太大差别的,我们不用太关注这一点。2.阻塞I

17、/O以及非阻塞I/O文件读写通常有阻塞和非阻塞两种方式,其中阻塞方式是我们比较常见的一种方式,此时函数会阻塞至操作完成。例如,对于如下一个等待用户输入字符串,并在屏幕上输出的例子:#include <unistd.h>#include <stdlib.h>int main(void) char buf10; int n = read(STDIN_FILENO, buf, 10); write(STDOUT_FILENO, buf, n); return 0; 执行该函数时,read函数会一直阻塞到在屏幕上输入数据并回车(此时STDIN有数据可用)为止。阻塞IO有一个很大

18、的问题是:无法实现并发。当同时进行多个IO操作的时候,前面的文件数据不可用的时候(往往是Socket之类的IPC操作),后面的IO操作无法执行。非阻塞IO则可以很好的解决这个问题,要使用非阻塞IO操作,需要在open的时候制定O_NONBLOCK标志。这样,如果设备暂时没有数据可读就返回-1,调用者应该试着再读一次(again)。这种行为方式称为轮询(Poll),调用者只是查询一下,而不是阻塞在这里死等,这样可以同时监视多个设备:#include <unistd.h>#include <fcntl.h>#include <stdlib.h>int main(

19、void) char buf10; /人为主动的定义了一个10字节的缓冲区域 int fd, n; fd = open("/dev/tty", O_RDONLY|O_NONBLOCK);/以只读&非阻塞I/O方式,系统调用打开文件:/dev/tty while (1) n = read(fd, buf, 10); /从打开的文件里面读取内容。 if (n >= 0) break; /if条件满足的时候跳出while(1)循环。 sleep(1); /本线程休眠1毫秒 write(STDOUT_FILENO, buf, n); close(fd); return

20、 0; *PS:为了示例函数简单,我这里没有考虑异常情况(如open失败)的处理,而这些是在实际项目中是必不可少的。非阻塞I/O有一个缺点,如果所有设备都一直没有数据到达,调用者则需要反复查询,这样会一直占着cpu不放。因此,在使用非阻塞I/O时,通常不会在一个while循环中一直不停地查询(这称为Tight Loop),而是每延迟等待一会儿来查询一下,以免做太多无用功,在延迟等待的时候可以调度其它进程执行。但是,这样又引入了一个新的问题,可能导致数据读取的不够及时,就拿我前面的例子来说,我在每次循环的时候Sleep了一秒。如果刚开始Sleep的时候数据可用,但此时却无法立即响应,需要到Sle

21、ep结束后钟才能输出结果。要解圆满解决这个问题,则需要用到select函数,它可以阻塞地同时监视多个设备,还可以设定阻塞等待的超时时间,由于select多见于socket编程场景,这里不大好举例,后续如果会介绍socket编程的时候再详细介绍它。3、文件描述符fd(File Discriptor,fd)Linux文件的身份证号码文件描述符是一个非负的整数,当打开一个文件或创建一个文件时,内核向进程返回一个标识该文件的整数,即fd。注意,若文件不被创建打开(即没有载入进程),是没有文件描述符可言的。必需明确一个概念:LINUX中的一切皆是文件。因此对于特殊的文件有特殊的文件描述符。特殊文件描述符

22、:0标准输入,1标准输出,2标准错误输出。三、Linux系统下的文件编程:Linux中文件编程可以使用两种方法:(1) Linux 系统调用(2) C语言库函数* 前者依赖于Linux系统,后者与操作系统是独立的,在任何操作系统下,使用C语言库函数操作文件的方式都是相同的。=C库函数调用其实实质上是对系统调用的再次封装。Linux文件编程方式常用函数/系统调用系统调用open (),read(),write(),lseek()库函数fopen(), fread(),fwrite(),flseek()说到I/O,估计做过硬件的人第一个反应就是芯片管脚的IO口。我刚开始也一直误解成某一个端口,后来

23、想想这个端口应该是广义上的端口,就是一种接口的概括,而不是特指某一个芯片腿。 在linux中用户通过进程控制来控制相关的系统调用来创建进程、实现进程调度、进程管理等。这些都是操作系统中的内核服务。为什么要用相关的系统调用,而不能直接访问内核呢,这是为了更好地保护内核空间所设计的机制。在linux中为了更好地保护内核空间,将程序的运行空间分为内核空间和用户空间(内核态和用户态)。分别运行在不同的级别上,逻辑是相互隔离的。因此用户进程在通常的情况下是不允许访问内核数据,也无法使用内核函数,他们只能在用户空间操作用户数据,掉用户空间的函数。 有些情况下,用户空间的进程需要获得一定的系统服务(调用内核

24、空间程序),这时操作系统就必须利用系统提供给用户的特殊接口,进入到内核空间的具体位置,操作完了之后,在退出来,回到用户空间。 系统调用只有250个左右,按照功能分为进程控制、进程间通信、文件系统控制、系统控制、存储管理、网络管理、socket控制、用户管理等。 系统调用并不是直接与程序员进行交互的,仅是通过一个软中断机制向内核提交请求,以获取内核服务的接口。这个编程接口是API,也有对应的API函数。 linux中对目录和设备的操作都等同于文件的操作,好家伙,这一下立刻就扩大了文件的定义,这样做的结果是可以大大简化系统对不同设备的处理,提高了效率。linux中的文件主要分为四种:普通文件、目录

25、文件、链接文件、设备文件。怎么突然感觉linux把什么都叫做文件了哦。 内核为了区分这些文件,就有了一个新的概念,文件描述符,就是之前常说的fd。一个进程启动的时候会打开3个文件:标准输入、标准输出和标准出错处理。这3个文件分别对应的文件描述符为0,1,2(也就是宏替换STDIN_FILENO、STDOUT_FILENO、STDERR_FILENO)。基于文件操作符的IO操作,常常是实现某些IO操作的唯一途径。 不带缓存的IO操作,主要有5个函数:open、read、write、lseek、close。线面对个函数进行一个简单的说明。 open函数:用于打开或创建文件,在打开或创建文件时可以指

26、定文件的属性及用户的权限等各种参数。 int open(const char *pathname,flags,int perms) pathname -> 被打开的文件名 flags:O_RDONLY -> 只读方式打开文件; O_WRONLY -> 可写方式打开文件; O_RDWR -> 读写方式打开文件; O_CREAT -> 如果该文件不存在,就创建一个新的文件,并用第三个参数为 其设置权限; O_EXCL -> 如果使用O_CREAT时文件存在,则可返回错误消息。这一参数可 测试文件是否存在; O_NOCTTY -> 使用本参数时,如文件为终端

27、,那么终端不可以作为调用 open()系统调用的那个进程的控制终端。 O_TRUNC -> 如文件已经存在,并且以只读或只写成功打开,那么会先全部 删除文件中原有数据。 O+APPEND -> 以添加方式打开文件,在打开文件的同时,文件指针指向文 件的末尾。 perm:被打开文件的存取权限,为8进制表示法。 成功返回文件描述符,失败返回-1CLOSE函数: close函数用于关闭一个打开的文件。当一个进程终止时,他所打开的文件都由内核自动关闭,很多程序都使用这一功能而不显示的关闭文件。 函数原型:int close(int fd) 成功返回0 失败返回-1 * 注意:open函数返

28、回的文件描述符一定是最小的未用文件描述符,若一个进程在启动时自动打开了0,1,2三个文件描述符,因此该文件运行结果中返回的文件描述符为3。READ函数: read函数是用于从指定的文件描述符中读取数据。当从终端设备中读出数据是通常一次最多读一行。 函数原型:ssize_t read(int fd,void *buf,size_t count) count:制定最大读出的字节数 成功:读到的字节数 0:已达到文件尾 -1:出错WRITE函数: write函数是用于向打开的文件写数据,写操作从文件的当前位移量处开始。若磁盘已满或超出该文件的长度,则write函数返回失败。 函数原型:ssize_t

29、 write(int fd,void *buf,size_t count) 成功:已写的字节数 -1:出错 LSEEK函数: lseek函数是用于在指定的文件描述符中将文件指针定位到相应的位置。 函数原型:off_t lseek(int fd,off_t offset,int whence) offset:偏移量,每一读写操作所需要移动的距离,单位是字节的数量,可正可负 whence:当前位置的基点。 SEEK_SET -> 当前位置为文件的开头,新位置为偏移量的大小; SEEK_CUR -> 当前位置为文件指针的位置,新位置为当前位置加上偏移量 SEEK_END -> 当前

30、位置为文件的结束,新位置为文件大小加偏移量的大小 成功:文件当前位置 -1:出错c语言中所有文件操作函数详解fopen、fwrite、fread、fgetc、fputc、fscanf、fprintf、ftell、fseek等函数在c中,文件操作都是由库函数来实现的,主要是分为读和写两种操作,以下详细讲解以下所有有关文件操作的邯郸乎的用法:(1)fopen()函数:打开文件包含头文件:#include<stdio.h>格式:FILE * fopen(const char * path,const char * mode);参数: path:需要打开的文件路径 mode:文件打开方式r

31、以只读方式打开文件,该文件必须存在r+以可读写方式打开文件,该文件必须存在rb+读写打开一个二进制文件,允许读数据。rt +读写打开一个文本文件,允许读和写w打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。w+打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。a以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留)a+以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容

32、会被保留。 (原来的EOF符不保留)wb只写打开或新建一个二进制文件;只允许写数据。wb+读写打开或建立一个二进制文件,允许读和写。wt+读写打开或着建立一个文本文件;允许读写。at+读写打开一个文本文件,允许读或在文本末追加数据。ab+读写打开一个二进制文件,允许读或在文件末追加数据。现在对上面的文件打开方式做个总结:文件使用方式由r,w,a,t,b,+六个字符拼成,各字符的含义是: r(read): 读 w(write): 写 a(append): 追加 t(text): 文本文件,可省略不写 b(banary): 二进制文件 +: 读和写返回值: 如果文件顺利打开,返回指向该流的文件指针

33、。如果文件打开失败则返回NULL,并把错误代码存在errno中。说明: 一般而言,打开文件后会作一些文件读取或写入的动作,若打开文件失败,接下来的读写动作也无法顺利进行,所以一般在fopen()后作错误判断及处理。(2)fread()函数和fwrite()函数:(可以用来实现对数据块的操作)1.一般调用形式 fread(buffer,size,count,fp); fwrite(buffer,size,count,fp);2.说明 (1)buffer:是一个指针,对fread来说,它是读入数据的存放地址。对fwrite来说,是要输出数据的地址。 (2)size:要读写的字节数; (3)coun

34、t:要进行读写多少个size字节的数据项; (4)fp:文件型指针。C语言还提供了用于整块数据的读写函数。 可用来读写一组数据,如一个数组元素,一个结构变量的值等。读数据块函数调用的一般形式为: fread(buffer,size,count,fp); 写数据块函数调用的一般形式为: fwrite(buffer,size,count,fp); 其中buffer是一个指针,在fread函数中,它表示存放输入数据的首地址。在fwrite函数中,它表示存放输出数据的首地址。 size 表示数据块的字节数。count 表示要读写的数据块块数。fp 表示文件指针。例如:fread(fa,4,5,fp);

35、 其意义是从fp所指的文件中,每次读4个字节(一个实数)送入实数组fa中,连续读5次,即读5个实数到fa中。(3)fgetc()和fputc():字符读写函数1.fgetc函数(getc函数) (1)一般调用形式 ch=fgetc(fp);(2)作用 从指定的文件读入一个字符,即从fp所指向的文件中读入一个字符赋给ch。(3)返回值 成功:返回值所得到的字符; 失败:返回EOF(-1)。2.fputc函数():(1)一般调用形式 fputc(ch,fp);(2)作用把一个字符写到磁盘文件上去,即将字符ch输出到fp所指向的文件中去。(3)返回值成功:返回值就是输出的字符;失败:返回EOF(-1

36、)。说明:函数putchar()是在stdio.h中用预处理命令定义的宏,即:#define putchar(c) fputc(c,stdout)4、fgets()和fputs()函数:读写字符串函数(1)fgets():char *fgets(char *str, int num, FILE *fp) 参数说明:str: 保存从文件读取出来的字符串 fp: 待读文件的文件指针 num: 表示从文件中读出的字符串不超过 n-1个字符。在读入的最后一个字符后加上串结束标志'0'(2)fputs(char * s,FILE * stream);5、fscanf()和fprintf(

37、)函数:格式化读写函数(1)fprintf()函数:输出格式化字符串到流或者是将格式化后的字符串写到输出流(文件)原型:int fprintf( FILE *stream, const char *format , argument ); 例子:fprintf(fp, "%s %s %d %f", str1,str2, a, b) ;(2)fscanf()函数:输出文件中的内容到某个变量中。原型:int fscanf(FILE *stream, char *format,argument.);int fscanf(文件指针,格式字符串,输入列表);for example:F

38、ILE *fp;char a;int b;double c;fscanf(fp,"%s%d%lf",a,&b,&c)返回值:整型,数值等于argument.的个数6、ftell()函数:得到流式文件的当前读写位置,其返回值是当前读写位置偏离文件头部的字节数。原型:long ftell(FILE *fp)7、 fseek()函数:把fp的文件读写位置指针移到指定的位置。原型:int fseek(FILE *fp,long offset,int origin);origin指的是“起始点”,它有三个常量的值,如下:起始点对应的数字 代表的文件位置SEEK_SET

39、 0 文件开头SEEK_CUR 1 文件当前位置SEEK_END 2 文件末尾8、 rewind()函数:将文件指针重新指向一个流的开头原型:int rewind(FILE *stream); 例子:一般我们会通过下面的方法来获取文件中字符的个数: FILE *fs=fopen("C:1.txt","r");/创建文件流 long length=0;/声明文件长度 fseek(fs,0,SEEK_END);/将文件内部指针放到文件最后面 length=ftell(fs);/读取文件指针的位置,得到文件字符的个数 rewind(fs);/将文件指针重置到文

40、件最前面*附:(几种POSIX以及C库API用法总结)*POSIX系统调用API:Open()函数:·所需头文件#include <sys/types.h>#include <sys/stat.h >#include <fcntl.h>函数原型(1)Int open(const char *pathname, int flags);(2)Int open(const char *pathname, int flags, mode_t mode );*当flag使用了O_CREAT标志,则使用第二种形式,这时需要mode来指定访问权限函数传入值Pat

41、hnamePathname:要打开的文件路径(缺省为当前路径)和文件名FlagsO_RDONLY:只读模式;Flags指定文件打开方式*必须三选一。O_WRONLT:只写模式O_RDWR:读写模式O_APPEND:每次写操作都写入文件的末尾;*Flags参数的附加选项,通过|与上面三个必须选项连接。O_CREAT:如果指定文件不存在,则创建这个文件;O_EXCL:如果要创建的文件已存在,则返回-1,并且修改errno的值,需要与O_CREAT配对使用以确保文件是新建的。O_TRUNC:如果文件存在,并且以只写/读写方式打开,则清空文件全部内容(即长度截短为0)。O_NOCTTY:如果路径名指向

42、终端设备,不要把这个设备用作控制中端;mode新建文件的权限信息。例:0777函数返回值成功返回文件描述符; 失败返回:-1;#include<unistd.h>#include<sys/types.h>#include<sys/stat.h>#include<fcntl.h>Viod main()int fd,size;char s =”Linux Programmer!n”,buffer80;fd=open(“/tmp/temp”,O_WRONLY|O_CREAT);write(fd,s,sizeof(s);close(fd);fd=open

43、(“/tmp/temp”,O_RDONLY);size=read(fd,buffer,sizeof(buffer);close(fd);printf(“%s”,buffer);Lseek函数:函数功能移动文件读写指针头文件#include <sys/types.h>#include <unistd.h>函数原型Off_t lseek(int fd, off_t offset, int whence)参数说明§Fd:文件描述符§offset:偏移量,正数表示正向偏移量,负数表示负向偏移量§whence:设定从文件的哪里开始偏移,可取值为:SE

44、EK_SET:文件开头SEEK_CUT:当前位置SEEK_END:文件结尾(其中SEEK_SET、SEEK_CUT、SEEK_END:0,1和2)返回值当调用成功则返回目前的读写位置相对头文件的偏移量,(即距文件开头多少字节,若有错误则返回-1,errno会存放错误代码)1. 欲将读写位置移到文件开头时:lseek(int fd, 0, SEEK_SET)2. 欲将读写位置移到文件结尾时: lseek(int fd, 0, SEEK_CUT)3. 欲将读写位置移到当前位置时:lseek(int fd, 0, SEEK_END)Read函数:函数功能由打开的文件中读取数据头文件#include

45、<unistd.h>函数原型Ssize_t read(int fd, void *buf , size_t count)参数说明§fd:文件描述符§buf:存放读取数据的缓冲区§count:读取的最大长度(字节数)返回值成功返回实际读取的字节数,失败返回-1Write函数:函数功能向文件写入一个数据块头文件#include<unistd.h>函数原型Ssize_t write(int fd ,const void *buf ,size_t count)参数说明§fd:文件描述符§buf:写入数据的缓冲区§count:写入数据的最大长度(总字节数)返回值成功返回实际写入字节数,当有错误发生时则返回-1,错误代码存入errno*C语言库函数:fopen()函数函数功能打开文件头文件#include<stdio.h>函数原型FILE *fopen(const char *path ,const char *mode)参数说明 path:欲打开的文件路径与文件名 mode:打开方式: “r”:以只读方式打开文件 “r+”:以可写可读方式打

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论