linux——文件编程

一、创建模式

使用"ls -l"命令,可以看到下图所示,其中红圈- rwx rwx r-x分别

-:代表普通文件
“rwx” :代表我自己对于该文件的权限为可读、可写、可执行,4 2 1
“rwx” :代表同组对于该文件的权限为可读、可写、可执行,4 2 1
"r-x" :代表其他组对于该文件的权限为可读、可执行,4 1
  • 常见创建模式
宏表示数字
S_IRUSR4 可读
S_IWUSR2 可行
S_IXUSR1 可执行
S_IRWXU7 可读可写可执行

在这里插入图片描述

二、创建文件creat()函数

int creat(const char *filename,mode_t mode)
filename:要打开的文件名(含路径,缺省为当前路径)
mode:创建模式 

三、open()函数—文件打开,close()

在这里插入图片描述
使用“man 2 open”命令可以看到open()函数有两个原型,并且它返回的是一个文件描述符(每个文件打开后会有一个自己的文件描述符,相当于自己的id,以后要打开那个文件就使用它自己的文件描述符),失败返回-1;

  • 参数说明
int open(const char *pathname,int flags);
int open(const char *pathname,int flags,mode_mode);
pathname要打开的文件名(含路径,缺省为当前路径)
flags
O_ RDONLY只读打开
O_WRONLY只写打开
O_RDWR可读可写打开

当我们附带权限后,打开的文件就只能按照这种权限来操作。
以上这三个常数中应当只指定一个,下列常数是可选择的:

O_CREAT若打开的文件不存在则创建它,使用此选项时,需要同时说明第三个参数mode,用其说明该新文件的存取许可权限,例:open(“file”,O_RDWR "竖线"O_CREAT,0600)
O_EXCL如果同时指定了O_CREAT,而文件已经存在,则出错,fd返回-1,并且不打开文件
O_APPEND每次写时都加到文件的末尾
O_TRUNC属性去打开文件时,如果这个文件中本来是有内容的,而且为只读或只写成功打开,则将其长度截短为0(把原先的内容干掉,再写)
mode一定是在flags中使用了O_CREAT标志,mode记录待创建的文件的访问权限
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
        int fd=open("file",O_RDWR);
        if(fd==-1){
                printf("open fall!!!\n");
                fd=open("file",O_RDWR|O_CREAT,0600);
                if(fd>0){
                        printf("create successful!!\n");
                }
        }
        close(fd);
}
open fall!!!
create successful!!
每次open完文件后一定要close文件!!!!!!!

四、写入write()函数

  • 原型及头文件
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
  • 参数说明
ssize_t返回值返回写入数据的大小
fd文件标识符
buf存放写入内容的指针变量
count要写入的大小
  • 注:如果先后往fd里写入两次数据,那么读取时第一次读到的是前一次数据,第二次对到的是后一次数据

五、光标移动lseek()函数

  • 函数原型
   #include <sys/types.h>
   #include <unistd.h>
   off_t lseek(int fd, off_t offset, int whence);
  • 参数说明
off_t成功完成后,lseek()返回得到的偏移位置- 从文件开始以字节为单位。在出现错误时, 返回值-1
fd文件标识符
offset此时光标要偏移的偏移量,可以用来判断文件大小
whence1.SEEK_SET 2.SEEK_CUR 3.SEEK_END
SEEK_SET文件头
SEEK_CUR光标当前位置
SEEK_END文件尾
  • 说明:将文件读写指针相对whence移动offset个字节
  • lseek()计算文件大小:
int size=lseek(fd,0,SEEK_END);
lseek(fd,0,SEEK_SET);//计算完别玩了把光标放到文件头,这样read才有数据

六、读出read()函数

  • 原型及头文件
       #include <unistd.h>
       ssize_t read(int fd, void *buf, size_t count);
  • 参数说明
ssize_t返回值返回写入数据的大小
fd文件标识符
buf存放读出内容的指针变量
count要读出的大小

read最多读文件大小,write可以无限写

七、open(),write(),lseek(),read(),close()操作演示

#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include<string.h>
#include<stdlib.h>
int main()
{
        char *buf="linux ubtuntu file programme!";
        int fd=open("file",O_RDWR|O_CREAT,0600);
        if(fd==-1){
                printf("open fall!\n");
                exit(0);
        }
        int a=strlen(buf);
        printf("buf=%d\n",a);
        int n_write=write(fd,buf,strlen(buf));
        int filesize=lseek(fd,0,SEEK_SET);
        printf("filesize=%d\n",filesize);
        char *readbuf=(char *)malloc(n_write);
        memset(readbuf,'\0',n_write);
        int n_read=read(fd,readbuf,n_write);
        printf("n_read=%d\n",n_read);
        
        close(fd); //每次open()完文件后一定要close();
}

八、文件操作原理简述

  • 我们对文件进行操作时,一定要先打开文件,打开成功之后才操作,如果打开失败,就不用进行后边的操作了,最后读写完成后,一定要关闭文件,否则会造成文件损坏。

  • 文件平时是存放在块设备中的文件系统文件中的,我们把这种文件叫静态文件,当我们去open打开一个文件时,linux内核做的操作包括:内核在进程中建立一个打开文件的数据结构,记录下我们打开的这个文件;内核在内存中申请一段内存,并且将静态文件的内容从块设备中读取到内核中特定地址管理存放(动态文件)。

  • 打开文件以后,以后对这个文件的读写操作,都是针对内存中的这一份动态文件,而不是针对静态文件的,当然我们对动态文件进行读写以后,此时内存中动态文件和块设备文件中的静态文件就不同步了,当我们close关闭动态文件时,close内部内核将内存中的动态文件的内容去更新(同步)块设备中的静态文件。

  • 为什么这么设计,不直接对块设备直接操作?
    块设备本身读写非常不灵活,是按块读写的,而内存是按字节单位操作的,而且可以随机操作,很灵活。

九、文件标志输入输出

  • 对于内核而言,所有打开文件都由文件描述符引用。文件描述符是一个非负整数。当打开一个现存文件或者创建一个新文件时,内核向进程返回一个文件描述符。当读写一个文件时,用open和creat返回的文件描述符标识该文件,将其作为参数传递给read和write。
    按照惯例,UNIX shell使用文件描述符0与进程的标准输入相结合,文件描述符1与标准输出相结合。STDIN_FILENO、STDOUT_FILEND、STDERR_FILENO这几个宏代替了0,1,2这几个数。
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<unistd.h>
#include<string.h>
int main()
{
        char readbuf[128];
        read(0,readbuf,128);
        write(1,readbuf,strlen(readbuf));
        return 0;

}


十、小练习

  1. 实现cp命令
#include<unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void panduanargc(int argc)
{

        if(argc<2){
                printf("cp: missing file operand\n");
                printf("Try 'cp --help' for more information.\n");
                exit(0);
        }

}
int main(int argc,char **argv)
{
        char *readbuf=NULL;
        panduanargc(argc);
        int fd1=open(argv[1],O_RDWR);
        if(fd1==-1){
                printf("cp: missing destination file operand after '%s'\n",argv[1]);
                printf("Try 'cp --help' for more information.\n");
                exit(0);
        }

        int fd2=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);
        //以可读可写打开,没有就创建,并且删除其中所有内容,
        if(fd2<0){
                printf("%s create fall!\n",argv[2]);
        }

        int size=lseek(fd1,0,SEEK_END);
        lseek(fd1,0,SEEK_SET);
        readbuf=(char *)malloc(size);
        int n_read=read(fd1,readbuf,size);

        write(fd2,readbuf,size);
        close(fd1);
        close(fd2);
        return 0;
}


                                                                        37,1-8        77%

  1. 修改file文件中的LONG=9
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>

int main()
{
        char *readbuf=NULL;
        int fd = open("./file",O_RDWR);
        if(fd==-1){
                printf("open fall!!!\n");
                exit(0);
        }
        int size=lseek(fd,0,SEEK_END);
        lseek(fd,0,SEEK_SET);

        readbuf=(char *)malloc(size);
        memset(readbuf,'\0',size);
        int n_read=read(fd,readbuf,size);
        char *p=(char *)malloc(size);
        p=strstr(readbuf,"LONG=");
        for(int i=0;i<5;i++){
                p++;
        }
        *p='9';
        lseek(fd,0,SEEK_SET);
        write(fd,readbuf,size);

        close(fd);

        return 0;
}

  1. 文件写入整形数和结构体
  • 写入整形数

ssize_t write(int fd, const void *buf, size_t count);
因为buf是void形,所有只需要传入变量的地址就行:

#include<sys/types.h>
int main()
{
	int fd;

	int data=100;
	int data2=0;
	
	fd=open("./file1",O_RDWR);

	int n_write=write(fd,&data,sizeof(int));
	
	lseek(fd,0,SEEK_SET);
	int n_read=read(fd,&data2,sizeof(int));

	printf("read %d\n",data2);	
	close(fd);
	
	return 0;
}

值得注意的是,file文件打开以后显示的是乱码,但并不影响我们read其中的内容,计算机会自动识别;

  • 写入结构体
#include<sys/types.h>
struct Test
{
	int a;
	char c;
}
int main()
{
	int fd;

	struct Test data={100,'a'};
	struct Test data2;
	
	fd=open("./file1",O_RDWR);

	int n_write=write(fd,&data,sizeof(struct Test));
	
	lseek(fd,0,SEEK_SET);
	int n_read=read(fd,&data2,sizeof(struct Test));

	printf("read %d,%c\n",data2.a,data2.c);	
	close(fd);
	
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值