Day26、文件操作(write)、文件的附加属性、文件重定向、mmap映射文件

来源:互联网 发布:ewb电路仿真软件 编辑:程序博客网 时间:2024/06/15 23:38

昨天作业:文件显示  Mycat函数:

  1#include<stdio.h>

  2#include<sys/types.h>

  3#include<fcntl.h>

  4#include<sys/stat.h>

  5#include<unistd.h>

  6int main(int argc,char *argv[]){

 7     int fd,ret;

 8     char buf;

 9     if(argc!=2){

 10        printf("usage:mycat filename\n");

 11        return 2;

 12     }

 13    //以只读的方式打开文件

 14    fd=open(argv[1],O_RDONLY);

 15    if(fd= =-1){

 16        perror("open");

 17        return 1;

 18     }

 19        while((ret=read(fd,&buf,1))>0){

 20            printf("%c",buf);

 21        }

 22    //关闭文件

 23    close(fd);

24     return 0;

 25 }

tarena@tarena-virtual-machine:~/day26$ gccmycat.c

tarena@tarena-virtual-machine:~/day26$./a.out

usage:mycat filename

tarena@tarena-virtual-machine:~/day26$./a.out hello.c

#include<stdio.h>

int main(){

   printf("c\n");

   return 0;

}

一、   文件操作的遗留部分

write (2)

 

#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);

功能:将buf里的内容,写入到文件描述符为fd的文件里,预计写入count个字节

参数:

fd:文件描述符

buf:指定的一个地址

count:欲写入的字节数

返回值:

返回写入的字节数,如果写入失败,返回-1,且errno被设置

举例:write.c

  1 #include<stdio.h>

  2#include<sys/types.h>

  3 #include<fcntl.h>

  4 #include<sys/stat.h>

  5 #include<unistd.h>

  6 #include<string.h>

  7 int main(int argc,char*argv[]){

  8     int fd,ret;

  9     char buf[12]="tang";

 10     if(argc!=2){

 11         printf("usage:mycatfilename\n");

 12         return 2;

 13     }

 14     //以写的方式打开文件

 15    fd=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0644);

 16     if(-1= =fd){

 17         perror("open");

 18         return 1;

 19     }

 20     //将buf数组里的内容写入到文件里

 21     write(fd,buf,strlen(buf)+1);

 22         //关闭文件

 23     close(fd);

 24     return 0;

 25 }

tarena@tarena-virtual-machine:~/day26$ ./a.out ss.txt

tarena@tarena-virtual-machine:~/day26$ cat ss.txt

tang

 

 

举例:进一步改写myacat.c

#include<stdio.h>

#include<sys/types.h>

#include<fcntl.h>

#include<sys/stat.h>

#include<unistd.h>

int main(int argc,char *argv[]){

   int fd,ret;

   char buf;

   if(argc!=2){

       printf("usage:mycat filename\n");

       return 2;

    }

   //以只读的方式打开文件

   fd=open(argv[1],O_RDONLY);

   if(fd==-1){

       perror("open");

       return 1;

    }

       while((ret=read(fd,&buf,1))>0){

           //文件描述符1代表标准输出

           write(1,&buf,1);       //前面的1代表标准输出(输出到屏幕,如果是fd就是输出到前面open打开的文件里)

        }

   //关闭文件

   close(fd);

   return 0;

}

tarena@tarena-virtual-machine:~/day26$./a.out  myacat.c

补充

1、  在文件操作中,尽量使用同一类的函数。

类有两种,(系统调用、库函数)

2、  文件描述符0、1、2(特殊的文件描述符)

UC:

0代表标准输入  STDIN_FILENO     (scanf)

1代表标准输出  STDOUT_FILENO     (printf)

2代表标准错误  STDERR_FILENO

标C:

0:stdin

1:stdout

2:stderr

3、  文件的每一行最后一个字符是\n

作业:封装一个函数,实现读取文件一行的功能

readline.c

 

lseek(2)

#include <sys/types.h>

#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);

举例

a.txt      abcdefghijkl

lseek.c

  1 #include<stdio.h>

  2 #include<sys/types.h>

  3 #include<sys/stat.h>

  4 #include<fcntl.h>

  5 #include<unistd.h>

  6 int main(int argc,char*argv[]){

  7     int fd;

  8     char buf;

  9     fd=open("a.txt",O_RDONLY);

 10     if(fd==-1){

 11         perror("open");

 12         return 0;

 13     }

 14     //3L 3是长整型,后面跟L是长整形,若U是无符号型

 15     lseek(fd,3L,SEEK_SET);

 16     read(fd,&buf,1);

 17     printf("%c\n",buf);  //从第三个后,第4个开始

 18

 19     lseek(fd,-2,SEEK_CUR);

//读完d后,位置定到de之间,接下来要读e,-2表示往前挪两个,到bc之间,所以读出c

 20     read(fd,&buf,1);

 21     printf("%c\n",buf);

 22     close(fd);

 23     return 0;

 24 }

tarena@tarena-virtual-machine:~/day26$ ./a.out

d

c

作业:写文件复制命令!!!!!!打包到库文件  unix高级环境编程》>

cp      源文件 目的文件

mycp    源文件 目的文件

实现文件的复制      (认真考虑每个细节)

 

二、          文件的附加属性(文件的元数据)


之前操作的是文件的内容,现在操作文件的属性

-rw-rw-r-- 1tarena tarena 13  9月 1 11:04 a.txt

除了文件的名字以外,其它都是文件的属性

每个文件都有且只有一个对应的inode(图在笔记上)

如果两个文件的inode是同一个,则这两个文件是硬链接文件,1硬链接数

(软链接是快捷方式)

tarena@tarena-virtual-machine:~/day26$ ls-l a.txt

-rw-rw-r-- 1 tarena tarena 13  9月  1 11:04 a.txt

tarena@tarena-virtual-machine:~/day26$ ln a.txt b.txt

tarena@tarena-virtual-machine:~/day26$ ls-l a.txt

-rw-rw-r-- 2 tarena tarena 13  9月  1 11:04 a.txt

查看inode的内容命令:

stat 文件名

tarena@tarena-virtual-machine:~/day26$ stata.txt

  文件:"a.txt"

  大小:13            块:8          IO 块:4096   普通文件

设备:801h/2049d Inode:1067314     硬链接:2

权限:(0664/-rw-rw-r--)  Uid:( 1000/  tarena)   Gid:( 1000/  tarena)

最近访问:2016-09-0111:14:05.027827759 +0800

最近更改:2016-09-0111:04:18.407843943 +0800

最近改动:2016-09-0111:39:22.339785767 +0800

创建时间:-

tarena@tarena-virtual-machine:~/day26$ statb.txt

  文件:"b.txt"

  大小:13            块:8          IO 块:4096   普通文件

设备:801h/2049d Inode:1067314     硬链接:2

权限:(0664/-rw-rw-r--)  Uid:( 1000/  tarena)   Gid:( 1000/  tarena)

最近访问:2016-09-0111:14:05.027827759 +0800

最近更改:2016-09-0111:04:18.407843943 +0800

最近改动:2016-09-0111:39:22.339785767 +0800

创建时间:-

tarena@tarena-virtual-machine:~/day26$

ab对应同一个inode

文件属性在inode里,如果获得inode里的文件属性信息?  fstat ( 2 )

man 2 fstat

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

int fstat(int fd, struct stat *buf);

(struct stat*buf ,通过这个参数可以带回一个值(在这个函数里把数写在这个地址里),这种参数叫做“值__结果参数”)

功能:将fd指定文件的inode中文件的属性信息通过buf带回

参数:

fd:文件描述符

buf:用来带回inode中文件的属性信息

返回值:

0:成功

-1:失败,errno被设置

掌握struct stat结构体每个字段的含义

struct stat {

               ino_t     st_ino;    /* inode number */    inode号

               mode_t    st_mode;   /* protection */     权限

               nlink_t   st_nlink;  /* number of hard links */   硬链接数

               uid_t     st_uid;    /* user ID of owner */      用户id

               gid_t     st_gid;    /* group ID of owner */     组id

               off_t     st_size;   /* total size, in bytes */      文件的字节数

 

               time_t    st_atime;  /* time of last access */         最后访问时间

               time_t    st_mtime;  /* time of last modification */   最后修改时间

               time_t    st_ctime;  /* time of last status change */   最后更新时间

          };

举例练习:

tarena@tarena-virtual-machine:~/day26$ ls-l a.txt

-rw-rw-r-- 2 tarena tarena 13  9月  1 11:04 a.txt

vi fstat.c

  1#include<stdio.h>

  2#include<time.h>

  3#include<sys/types.h>

  4#include<sys/stat.h>

  5#include<unistd.h>

  6int main(int argc,char *argv[]){

 7     struct stat sb;

 8     int ret;

 9     //获取inode中的文件属性信息

 10    ret=stat(argv[1],&sb);

 11    if(ret==-1){//失败

 12        perror("stat");

 13        return 1;

 14     }

 15    printf("stat successful.....\n");

 16    //输出文件的inode号

 17    printf("inode number....%ld\n",(long)sb.st_ino);

 18    //输出文件的权限

 19    printf("mode:%lo\n",(unsigned long)sb.st_mode);

 20    //输出文件的大小

 21     printf("size:%lld\n",(longlong)sb.st_size);

 22    //输出文件的uid和gid

 23    printf("uid:%ld\tgid:%ld\n",(long)sb.st_uid,(long)sb.st_gid);

 24    //输出文件时间

 25    printf("Last status change: %s\n",ctime(&sb.st_ctime));

 26    return 0;

 27 }

tarena@tarena-virtual-machine:~/day26$ gccfstat.c

tarena@tarena-virtual-machine:~/day26$./a.out  a.txt

stat successful.....

inode number....1067314

mode:100664

size:13

uid:1000  gid:1000

Last status change: Thu Sep  1 11:39:22 2016

 

tarena@tarena-virtual-machine:~/day26$ stata.txt

  文件:"a.txt"

  大小:13            块:8          IO 块:4096   普通文件

设备:801h/2049d Inode:1067314     硬链接:2

权限:(0664/-rw-rw-r--)  Uid:( 1000/  tarena)   Gid:( 1000/  tarena)

最近访问:2016-09-0111:14:05.027827759 +0800

最近更改:2016-09-0111:04:18.407843943 +0800

最近改动:2016-09-0111:39:22.339785767 +0800

创建时间:-

tarena@tarena-virtual-machine:~/day26$

(vi stat.c +23 直接到23行)

getpwuid (3)   man getpwuid

getpwnam 得到文件名的函数 显示a.txt

getgrgid (3)

ctime(3)

作业:myls的实现!! (注意将一些功能封装成函数)

三、文件描述符的复制

dup  (2)

#include <unistd.h>

int dup(intoldfd);

功能:复制oldfd文件描述符到新的文件文件描述符中

参数: oldfd    旧的fd

返回值:

-1:失败  errno被设置

成功返回新的描述符,这个描述符是最小的没有被使用的文件描述符

dup2

int dup2(intoldfd, int newfd);

功能:将旧的文件描述符复制给新的文件描述符

参数:

Oldfd:旧文件描述符

Newfd新文件描述符

返回值

-1:失败  errno被设置

成功返回新的描述符,这个描述符是最小的没有被使用的文件描述符

举例:dup.c  重要

  1 #include<stdio.h>

  2 #include<sys/stat.h>

  3 #include<sys/types.h>

  4 #include<fcntl.h>

  5 #include<unistd.h>

  6 #include<string.h>

  7 int main(){

  8    int fd,s_fd;

  9    char *msg="this is a test\n";

 10    //fd=3,3指向文件

 11    fd=open("somefile",O_RDWR|O_CREAT,0644);

 12    if(fd==-1){

 13        perror("open");

 14        return 1;

 15     }

 16    //s_fd=4

 17    s_fd=dup(STDOUT_FILENO);

 18    dup2(fd,STDOUT_FILENO);//1、3、4都指向文件somefile

 19    close(fd);//文件描述符3给关掉

 20    write(STDOUT_FILENO,msg,strlen(msg));

 21    //改变了标准输出文件描述符的方向

 22    dup2(s_fd,1);//将s_fd复制给1

 23    //本来输入到屏幕上,现在输出到文件somefile里

24     //重定向

 25    write(STDOUT_FILENO,msg,strlen(msg));

 26    close(fd);//文件描述符3给关掉

 27    return 0;

 28 }

tarena@tarena-virtual-machine:~/day26$./a.out

this is a test

文件重定向的原理:dup.c

四、 mmap映射文件

使用read/write读写文件,效率比较低

为了提高效率,使用mmap将文件直接映射到虚拟地址空间里。对这块内存空间的操作,直接反映到文件里。

举例:

首先写个文件:

tarena@tarena-virtual-machine:~/day26$vi hello

tarena@tarena-virtual-machine:~/day26$od -tx1 -tchello  命令

0000000  68 65  6c  6c 6f  0a

                   h  e   l   l  o  \n

0000006

 

vi mmap.c

  1 #include<sys/mman.h>

  2 #include<stdio.h>

  3 #include<sys/types.h>

  4 #include<sys/stat.h>

  5 #include<fcntl.h>

  6 #include<unistd.h>

  7 int main(){

  8    int fd;

  9    fd=open("hello",O_RDWR);

 10    if(fd==-1){

 11        perror("open");

 12        return 1;

 13     }

 14    void *handle=mmap(NULL,6,PROT_WRITE,MAP_SHARED,fd,0);

 15    if(handle= =MAP_FAILED){

 16        perror("mmap");

 17        return 2;

 18     }

 19    int *p=(int *)handle;

 20    p[0]=0x30313233;

 21    close(fd);

 22    munmap(handle,6);

 23    return 0;

24 }

 

tarena@tarena-virtual-machine:~/day26$gcc mmap.c

tarena@tarena-virtual-machine:~/day26$./a.out

tarena@tarena-virtual-machine:~/day26$od -tx1 -tc hello

0000000  33 32  31  30 6f  0a

                   3  2   1   0  o  \n       

0000006

前4个字节变了,因为程序中int*p=(int *)handle;,只改了int 型个字节,int是4个字节

0 0
原创粉丝点击