文件I/O

      这一章说的主要内容也就是文件输入输出有关的操作。文件的操作也就几种操作而已,创建文件,文件打开,关闭,文件的读写另外加上文件的当前指针位置的各种操作。   

      先从文件的创建来开始说起,int  open(const char *pathname,int flag,.../* mode_t   mode*/);    open函数返回一个文件描述符,一般来说返回的都是进程文件描述符中最小的一个。一个进程从运行开始一般都会打开三个文件,标准输入,标准输出,和标准出错函数。三个对应的文件描述符分别是0,1,2.所以一般第一次打开一个文件的描述符是从三开始的。想让进程使用的描述符是2的话,可以先把标准出错关闭掉,然后在创建或者打开文件的话,那么文件的描述符就应该是2的。而下面还会有个函数,可以轻易的实现在某个描述符上操作文件。对于创建一个文件来说,mode是必须的,这个位是标志文件的权限的,文件的权限有读写执行。分三组,用户读写执行,用户组读写执行,和其他的读写执行。在头文件中定义,同标准输入标春输出用STDOIN_FILENO,STDOUT_FILENO,表示一样。但是我们同样可以用数字表示,三个数字421分别对应这读写执行操作,这三个数字可以对应七个数字,分别对应不同的权限,例如open("hello.c",o_creat|o_wronly,0774),就表示对于hello文件来说用户有读写执行的权限,所在用户组成员有读写执行的权限,而其他人只有读的权限。就是这样的组合的。而关于中间的flag,也是有很多的组合,如果对于需要创建文件的话,可以用flag|O_CREAT来添加各种的权限。有打开读打开写,追加之类的各种操作的。具体就看怎么使用得了。虽然有文件的创建操作,但是对于相当与带有参数的open函数一样,open函数就可以执行所有的操作了。

       有了文件的打开,当然就需要有文件的操作了,文件的操作也很简单,个人觉得很好的地方就是函数直接了当,能从函数上看出函数所执行的操作,打开就open,关闭就close。读文件就read,写文件就write。很好,很容易记住,也很好使用。read函数返回读入的字符的个数,write函数返回写入的字符的个数。还有就是文件当前指针定位的函数。lseek函数有三个参数off_t lseek(int filds,off_t offset,int whence)  whence 有三个值,分别对应这文件的开始,现在指针位置和文件的末尾。而offset是相对与whence的偏移量。你可以创建一个文件在开始写几个字符,然后便宜几万各字符再写几个字符。这样的文件就会出现一种情况,文件空洞的情况。所以你会发现很多情况下文件的结尾位置很大,但是文件并没有那么大的情况。但是如果你对文件重定向到另一个文件中的话,文件中的空洞就会被填充了。

       对于文件追加和lseek的情况,和open追加的情况还是不同的,这就是需要理解原子操作的情况,还需要对linux的文件系统有一定的理解才行。如果是open用追加的方式打开的话,那么每次写的时候就能够保证写在文件的末尾了,但是如果你用lseek定位的话在定位结束以后有其他进程还可能对文件进行追加的话,那么文件的末尾就会变了,所以再继续往文件内添加内容的话就会出现文件被覆盖的情况了,还是需要理解两者之间的区别的

       文件描述符的操作有两个函数dup(int filds)和dup(int fids,int fidls2);dup函数的参数是一个文件描述符,返回值是一个文件描述符。对这两个文件描述符的操作都是对一个文件的操作,但是中间还是有一点点疑问没有搞清楚,就是如果关闭一个另一个会出现什么情况?两个文件是不是共同使用相同的偏移量的问题,还是需要实验的。而对于函数dup2的话就是复制第一各参数到第二各参数,这样就能够实现在固定描述符上实现对同一个文件的操作。

     对于文件其他的操作全部集中在fcntl函数上,而且很多函数都可以用fcntl函数来进行,也就是fcntl函数的一个变体而已。就像文件权限的设置,文件权限的获取等等。参数很多,需要的时候自己看书就行了。而更多其他的操作就在iotel函数中。这个函数还没有见到用过,遇到具体的情况的时候再作处理。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#define BUFFSIZE 2048

int main(int argc,char *argv[])
{
     int fd,n,i;
     char buf[BUFFSIZE];
     fd=open(argv[1],O_CREAT|O_RDWR,0754);
     if(fd<0){
	perror("fail to creat file!");
	exit(1);
     }
     //打开传入的参数的文件

     n=read(fd,buf,sizeof(buf));
     printf("input %d charactor.\n",n);
     //把文件中的内容读入buf数组中

     n=lseek(fd,0,SEEK_CUR);
     printf("file length:%d\n",n);
     //lseek用来测试文件的长度,
    
     n=write(STDOUT_FILENO,buf,n);
     //把buf中的内容写到标准输出中也就是屏幕上
     printf("\n ouput %d charactor.\n",n);

     return 0;
}

当文件描述符复制的时候,两个文件描述符操作统一个文件,共享文件的偏移量。而且就算一个文件描述符关闭并不影响另一各文件描述副的操作。下面打开一个文件,然后复制文件描述副,通过两个文件描述符分别写入两个字符串,然后关掉一个文件描述符,从另一个读出写入的字符输出到屏幕上。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#define BUFFSIZE 1024

int main(int argc,char *argv[])
{
    int fd1,fd2,n=0;
    char *buf1="hello";
    char *buf2="world!";
    char buf[BUFFSIZE];
 
    fd1=open(argv[1],O_RDWR|O_CREAT,0754);
    if(fd1<0){
	perror("fail to creat new file!");
	exit(1);
    }

    fd2=dup(fd1);
    printf("fd1:%d  fd2:%d\n",fd1,fd2);
    printf("sizeof buf1 %d   sizeof buf2  %d\n",strlen(buf1),strlen(buf2));

    write(fd1,buf1,strlen(buf1));
    printf("fd1 length:%d\n",lseek(fd1,0,SEEK_CUR));
    write(fd2,buf2,strlen(buf2));
    printf("fd2 length:%d\n",lseek(fd2,0,SEEK_CUR));
    close(fd1);

    lseek(fd2,0,SEEK_SET);
    n=read(fd2,buf,BUFFSIZE);
    buf[n]='\0';
    printf("%s\n",buf);
    close(fd2);   
    return 0;
}

对一个文件开始写如十个字符,然后把文件指针偏移向后移动10240各字节,然后再写入一个字符串,同样打开另外一个文件,把第一个文件读出写入到第二个文件中。然后用stat命令查看两个文件就会发现第一各文件所用磁盘块小于第二个的磁盘块

#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<string.h>
#include<unistd.h>
#define BUFFSIZE 4048
int main(int argc,char *argv[])
{
     int fd1,fd2,length;
     char *buf1="abcdefghij";
     char buf[BUFFSIZE];
     fd1=open(argv[1],O_CREAT|O_RDWR,0754);
     fd2=open(argv[2],O_CREAT|O_WRONLY,0754);
     
     write(fd1,buf1,strlen(buf1));
     lseek(fd1,10240,SEEK_CUR);
     write(fd1,buf1,strlen(buf1));
    
     lseek(fd1,0,SEEK_SET);
     while((length=read(fd1,buf,BUFFSIZE))>0)
	write(fd2,buf,length);
     
     close(fd1);
     close(fd2);
     return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值