Linux系统编程——文件编程

Linux系统编程——文件编程

1.文件概述

2.文件打开及创建

3.文件写入操作编程

4.文件读取操作

5.文件光标移动操作

6.文件打开创建的补充

7.文件操作原理

8.文件操作小应用之实现cp指令

1.文件概述

操作API完成自动化操作。

2.文件打开及创建

在这里插入图片描述

注意包含头文件:

 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>

函数原形:

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
open()返回一个文件描述符

在这里插入图片描述
在这里插入图片描述

2.1打开文件open(关键:返回文件描述符)

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>


int main()
{
        int fd;
        fd = open("./file1",O_RDWR); 	//打开文件file1
        printf("%d\n",fd);				//打印返回文件描述符符号,-1为打开失败
	
        return 0;
}

2.2创建并且打开文件 O_CREAT

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>


int main()
{
        int fd;
        fd = open("./file1",O_RDWR);
        if(fd == -1){
                printf("open file1 failed\n");
                fd = open("./file1",O_RDWR|O_CREAT,0600);	//0_CREAT创建文件 0600:权限可读可写
                if(fd > 0){
                        printf("%d\n",fd);
                }
        }
        return 0;
}

在这里插入图片描述

-rw------- -:普通文件 rw:可读可写
在这里插入图片描述

image-20230311140409520

2.3 O_EXCL可用来判断文件是否存在(配合O_CREAT使用)

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>


int main()
{
        int fd;
        fd = open("./file1",O_RDWR|O_CREAT|O_EXCL);// O_EXCL判断文件是否存在
        if(fd == -1){
                printf("create file1 failed\n");

        }
        return 0;
}

输出结果(当文件存在时)
在这里插入图片描述

2.4 O_APPEND

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
        int fd;
        char *buf = "this is buf";
        fd = open("./file1",O_RDWR|O_APPEND);	//O_APPEND在文件末尾后添加内容

        int n_write  = write(fd,buf,strlen(buf));
        if(n_write != -1){
                printf("write sizeof:%d\n ",n_write);

        }
        lseek(fd,0,SEEK_SET);
        char *readbuf;
        readbuf = (char *)malloc(sizeof(char) * n_write);
        int n_read = read(fd,readbuf,100);
        printf("read sizeof:%d ,context :%s\n",n_read,readbuf);
        close(fd);
        return 0;
}

结果输出:
在这里插入图片描述

程序运行前:
在这里插入图片描述

程序运行后:

在这里插入图片描述

若不加O_APPEND:会覆盖原有内容

在这里插入图片描述

2.5 O_TRUNC(擦除原有内容,重新写入)

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
        int fd;
        char *buf = "this is buf";
        fd = open("./file1",O_RDWR|O_TRUNC);//O_TRUNC(擦除原有内容,重新写入)

        int n_write  = write(fd,buf,strlen(buf));
        if(n_write != -1){
                printf("write sizeof:%d\n ",n_write);

        }
        lseek(fd,0,SEEK_SET);
        char *readbuf;	//野指针
        readbuf = (char *)malloc(sizeof(char) * n_write);//开辟空间
        int n_read = read(fd,readbuf,100);
        printf("read sizeof:%d ,context :%s\n",n_read,readbuf);
        close(fd);
        return 0;
}

输出结果:
在这里插入图片描述

程序运行前:
在这里插入图片描述

程序运行后:
在这里插入图片描述

2.6 creat创建文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rRZxS6hE-1681889538374)(C:\Users\passersby\AppData\Roaming\Typora\typora-user-images\image-20230312113922534.png)]

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>


int main()
{
        int fd;
        fd = creat("./file2",S_IRWXU);//S_IRWXU 可读可写可执行

        return 0;
}

输出结果:
在这里插入图片描述

3.文件写入操作编程

在这里插入图片描述

注意包含头文件:

 #include <unistd.h>

函数原形:

ssize_t write(int fd, const void *buf, size_t count);//从 void *buf 中读取 size_t count 个字节放入 int fd   返回写入的字节

使用:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
        int fd;
        char *buf = "this is buf";
        fd = open("./file1",O_RDWR);
        if(fd == -1){
                printf("open file1 failed\n");

                fd = open("./file1",O_RDWR|O_CREAT,0600);
                if(fd > 0){
                        printf("create file1 success! fd:%d\n",fd);
                }
        }

        write(fd,buf,strlen(buf));	// write(fd,buf,sizeof(buf)); Linux下只会显示8个字符 sizeof计算的是指针的长度,要用strlen
        close(fd);
        return 0;
}

4.文件读取操作

在这里插入图片描述

注意包含头文件:

 #include <unistd.h>

函数原形:

ssize_t read(int fd, const void *buf, size_t count);//从 fd 中读取 size_t count 个字节放入 void *buf

使用:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
        int fd;
        char *buf = "this is buf";
        fd = open("./file1",O_RDWR);
        if(fd == -1){
                printf("open file1 failed\n");

                fd = open("./file1",O_RDWR|O_CREAT,0600);
                if(fd > 0){
                        printf("create file1 success! fd:%d\n",fd);
                }
        }

        int n_write  = write(fd,buf,strlen(buf));
        if(n_write != -1){
                printf("write sizeof:%d ",n_write);

        }
        char *readbuf;
        readbuf = (char *)malloc(sizeof(char) * n_write);
        int n_read = read(fd,readbuf,n_write + 1);
        printf("read sizeof:%d ,context :%s\n",n_read,readbuf);
        close(fd);
        return 0;
}

结果:
在这里插入图片描述

读取到 0字节;光标问题;写入后光标在尾部,读取不到内容;可先关闭文件再开打文件,使光标在文件头;

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
        int fd;
        char *buf = "this is buf";
        fd = open("./file1",O_RDWR);
        if(fd == -1){
                printf("open file1 failed\n");

                fd = open("./file1",O_RDWR|O_CREAT,0600);
                if(fd > 0){
                        printf("create file1 success! fd:%d\n",fd);
                }
        }

        int n_write  = write(fd,buf,strlen(buf));
        if(n_write != -1){
                printf("write sizeof:%d\n ",n_write);

        }
        close(fd);
        open("./file1",O_RDWR);
        char *readbuf;
        readbuf = (char *)malloc(sizeof(char) * n_write);
        int n_read = read(fd,readbuf,n_write + 1);
        printf("read sizeof:%d ,context :%s\n",n_read,readbuf);
        close(fd);
        return 0;
}

输出结果:
在这里插入图片描述

5.文件光标移动操作

在这里插入图片描述

注意包含头文件:

#include <sys/types.h>
#include <unistd.h>

函数原形:

off_t lseek(int fd, off_t offset, int whence);//  off_t offset:偏移值  负数往前偏移,正数往后偏移  whence :位置  返回文件从头到尾偏移值
SEEK_SET	//头
SEEK_CUR	//当前位置
SEEK_END	//尾

使用:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
        int fd;
        char *buf = "this is buf";
        fd = open("./file1",O_RDWR);
        if(fd == -1){
                printf("open file1 failed\n");

                fd = open("./file1",O_RDWR|O_CREAT,0600);
                if(fd > 0){
                        printf("create file1 success! fd:%d\n",fd);
                }
        }

        int n_write  = write(fd,buf,strlen(buf));
        if(n_write != -1){
                printf("write sizeof:%d\n ",n_write);

        }
//      close(fd);
//      open("./file1",O_RDWR)
        char *readbuf;
        readbuf = (char *)malloc(sizeof(char) * n_write);

//      lseek(fd,0,SEEK_SET);
        lseek(fd,-n_write,SEEK_END); //off_t offset:偏移值  负数往前偏移,正数往后偏移 
        int n_read = read(fd,readbuf,n_write + 1);
        printf("read sizeof:%d ,context :%s\n",n_read,readbuf);
        close(fd);
        return 0;
}

输出结果:
在这里插入图片描述

可用lseek函数计算文件大小
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
        int fd;
        char *buf = "this is buf";
        fd = open("./file1",O_RDWR|O_CREAT,0600);

        int n_write  = write(fd,buf,strlen(buf));
        int fileSize = lseek(fd,0,SEEK_END);
        printf("file1 sizeof:%d\n",fileSize);
        close(fd);
        return 0;
}

6.文件打开创建的补充

已补充到[2.2、2.3、2.4、2.5](#2.2创建并且打开文件 O_CREAT)

7.文件操作原理

在这里插入图片描述

在这里插入图片描述

文件描述符(非负整数) = open(文件,)

Linux系统中默认:

012
标准输入标准输出标准错误

使用:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main()
{
        int fd;
        char readbuf[128];
		//ssize_t read(int fd, const void *buf, size_t count);//从 fd 中读取 size_t count 个字节放入 void *buf
        int n_read = read(1,readbuf,5);

        int n_write  = write(0,readbuf,strlen(readbuf));
        return 0;
}

在这里插入图片描述

静态文件动态文件
文件存在磁盘中open静态文件后,会在Linux内核产生结构体记录

read,write都是对动态文件进行操作,调用close,将缓存区存入磁盘

8.文件操作小应用之实现cp指令

参数 cp src.c des.c

012
cpsrc.cdes.c
argv[0]argv[1]argv[2]

argv[ ] :字符串数组

  1. C语言参数

  2. 思路

  • 打开src.c
  • 读src到buf
  • 打开/创建des.c
  • 将buf写入到des.c
  • 关闭两个文件

测试:

#include <stdio.h>

int main(int argc,char **argv)
{
	printf("total params:%d",agrc);
	printf("No.1 params:%d",agrv[0]);
	printf("No.2 params:%d",agrv[1]);
	printf("No.3 params:%d",agrv[2]);
	return 0;
}

输出结果:
在这里插入图片描述

使用:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
    	if(argc != 3){
                printf("params error\n");
                exit(-1);
        }
        int fdSrc;
        int fdDes;
  		//char readbuf[1024];		//直接定义大小会造成空间浪费或者不够用
        char *readbuf = NULL;		//缓冲区
        fdSrc = open(argv[1],O_RDWR);
        int fdSrcSize = lseek(fdSrc,0,SEEK_END);	//获取被拷贝文件大小
        lseek(fdSrc,0,SEEK_SET);	//将光标重新定位到文件头
        readbuf = (char *)malloc(sizeof(char)*fdSrcSize+8);	//根据需要拷贝文件大小来开辟空间
        int n_read = read(fdSrc,readbuf,fdSrcSize);		//从源文件读取内容到缓冲区
        fdDes = open(argv[2],O_RDWR|O_CREAT,0600);		//打开/创建目标文件
        int n_write  = write(fdDes,readbuf,strlen(readbuf));	//将缓冲区内容拷贝到目标文件
        close(fdSrc);	//关闭源文件
        close(fdDes);	//关闭目标文件,此时为静态文件放入磁盘中
        return 0;
}

9.解决拷贝的一些bug

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
    	if(argc != 3){
                printf("params error\n");
                exit(-1);
        }
        int fdSrc;
        int fdDes;
  		//char readbuf[1024];		//直接定义大小会造成空间浪费或者不够用
        char *readbuf = NULL;		//缓冲区
        fdSrc = open(argv[1],O_RDWR);
        int fdSrcSize = lseek(fdSrc,0,SEEK_END);	//获取被拷贝文件大小
        lseek(fdSrc,0,SEEK_SET);	//将光标重新定位到文件头
        readbuf = (char *)malloc(sizeof(char)*fdSrcSize+8);	//根据需要拷贝文件大小来开辟空间
        int n_read = read(fdSrc,readbuf,fdSrcSize);		//从源文件读取内容到缓冲区
        fdDes = open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);	//打开/创建目标文件,如果目标文件存在由内容就要使用O_TRUNC擦除原来内容,重新写入
        int n_write  = write(fdDes,readbuf,strlen(readbuf));	//将缓冲区内容拷贝到目标文件
        close(fdSrc);	//关闭源文件
        close(fdDes);	//关闭目标文件,此时为静态文件放入磁盘中
        return 0;
}

10.文件编程小应用之修改程序的配置文件

思路:

  • 找到需要修改的位置
  • 位置往后移
  • 修改参数

strstr函数

STRSTR(3)                 Linux Programmer's Manual                STRSTR(3)

NAME
       strstr, strcasestr - locate a substring

SYNOPSIS
       #include <string.h>

       char *strstr(const char *haystack, const char *needle); //函数查找字符串haystack第一次出现的子串needle 。 终止'\ 0'字符不进行比较。
/*
	参数 (Parameters)
		haystack - 这是要扫描的主要C字符串。
		needle - 这是用in-haystack字符串搜索的小字符串。
*/
       #define _GNU_SOURCE         /* See feature_test_macros(7) */

       #include <string.h>

       char *strcasestr(const char *haystack, const char *needle);

DESCRIPTION
       The  strstr()  function  finds  the first occurrence of the substring
       needle in the string haystack.  The terminating null bytes ('\0') are
       not compared.

       The  strcasestr()  function is like strstr(), but ignores the case of
       both arguments.

RETURN VALUE
       These functions return a pointer to the beginning of  the  substring,
       or NULL if the substring is not found.//返回值 这些函数返回一个指向子字符串开头的指针,如果子字符串没有找到,则为NULL。(返回一个字符串开头的指针,指向查找字符的头部)

使用:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
        if(argc != 2){
                printf("params error\n");
                exit(-1);
        }
        int fdSrc;
        char *readbuf = NULL;
        fdSrc = open(argv[1],O_RDWR);
        int fdSrcSize = lseek(fdSrc,0,SEEK_END);  //用lseek计算文件大小
        lseek(fdSrc,0,SEEK_SET);    //将光标重新定位到文件头
        readbuf = (char *)malloc(sizeof(char)*fdSrcSize+8);  //根据计算到的文件大小来开辟空间,避免空间的浪费
        int n_read = read(fdSrc,readbuf,fdSrcSize);  //将文件内容读取到
        char *p = strstr(readbuf,"LENG=");	//在 readbu 字符串中查找第一次出现"LENG="的位置
        if( p == NULL){	
                printf("No found\n");
                exit(-1);
        }
        p = p + strlen("LENG=");	//p承接的是strstr函数的返回值;返回一个字符串指针,并且指向第一次查找到字符串的头;p = p+strlen("LENG="),将位置偏移到 = 后.
        *p='5';	//修改参数
        int n_write  = write(fdSrc,readbuf,strlen(readbuf)); //重新写入参数

        close(fdSrc);
        return 0;
}

程序运行前:
在这里插入图片描述

程序运行后:
在这里插入图片描述

bug:会发现与所想的不一样(因为光标在文件末尾)

优化解决:

  1. 将光标重新定位到文件头
  2. 使用O_TRUNC
①优化实现思路一:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
        if(argc != 2){
                printf("params error\n");
                exit(-1);
        }
        int fdSrc;
        char *readbuf = NULL;
        fdSrc = open(argv[1],O_RDWR);
        int fdSrcSize = lseek(fdSrc,0,SEEK_END);
        lseek(fdSrc,0,SEEK_SET);
        readbuf = (char *)malloc(sizeof(char)*fdSrcSize+8);
        int n_read = read(fdSrc,readbuf,fdSrcSize);
        char *p = strstr(readbuf,"LENG=");	//在 readbu 字符串中查找第一次出现"LENG="的位置
        if( p == NULL){	
                printf("No found\n");
                exit(-1);
        }
        p = p + strlen("LENG=");	//p承接的是strstr函数的返回值;返回一个字符串指针,并且指向第一次查找到字符串的头;p = p+strlen("LENG="),将位置偏移到 = 后.
        *p='5';	//修改参数,要注意是字符!!
    	lseek(fdSrc,0,SEEK_SET);	//将光标重新定位到文件头;
        int n_write  = write(fdSrc,readbuf,strlen(readbuf)); //重新写入参数

        close(fdSrc);
        return 0;
}

程序运行后:
在这里插入图片描述

②优化思路二:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
        if(argc != 2){
                printf("params error\n");
                exit(-1);
        }
        int fdSrc;
        char *readbuf = NULL;
        fdSrc = open(argv[1],O_RDWR);
        int fdSrcSize = lseek(fdSrc,0,SEEK_END);
        lseek(fdSrc,0,SEEK_SET);
        readbuf = (char *)malloc(sizeof(char)*fdSrcSize+8);
        int n_read = read(fdSrc,readbuf,fdSrcSize);
        char *p = strstr(readbuf,"LENG=");      //在 readbu 字符串中查找第一次出现
"LENG="的位置
        if( p == NULL){
                printf("No found\n");
                exit(-1);
        }
        p = p + strlen("LENG=");        //p承接的是strstr函数的返回值;返回一个字符
串指针,并且指向第一次查找到字符串的头;p = p+strlen("LENG="),将位置偏移到 =.
        *p='5'; //修改参数
//      lseek(fdSrc,0,SEEK_SET);        //将光标重新定位到文件头;
        close(fdSrc); 
        fdSrc = open(argv[1],O_RDWR|O_TRUNC); //重新打开文件,并擦除原有内容
        int n_write  = write(fdSrc,readbuf,strlen(readbuf)); //重新写入参数

        close(fdSrc);
        return 0;
}

程序运行后:(结果也是可以的)
在这里插入图片描述

11.写一个整数到文件

使用:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
        int fdSrc;
        int data = 100;
        int data2 = 0;
        fdSrc = open("./file2",O_RDWR|O_CREAT);
   //ssize_t write(int fd, const void *buf, size_t count);//从 void *buf 中读取 size_t count 个字节放入 int fd   返回写入的字节
        int n_write  = write(fdSrc,&data,sizeof(int)); 
        lseek(fdSrc,0,SEEK_SET);
        int n_read = read(fdSrc,&data2,sizeof(int));
        printf("read:%d\n",data2);
        close(fdSrc);
        return 0;
}

结果:
在这里插入图片描述

在这里插入图片描述

人所看见是乱码,但不影响计算机实际读取

tips:发现一个有趣的现象

fdSrc = open("./file2",O_RDWR|O_CREAT); “./file2”,我写成了".file2",没有生成file2文件,这很正常,但也能读出结果。目前我认为这一切都是在缓冲区运行的,并没有直接读取
在这里插入图片描述

12.写结构体数组到文件

结构体写入文件:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
struct Test
{
        int data;
        char c;
};
int main(int argc,char **argv)
{
        int fdSrc;
        struct Test data = {200,'b'};
        struct Test data2;
        fdSrc = open("./file2",O_RDWR);
        int n_write  = write(fdSrc,&data,sizeof(struct Test)); //重新写入参数
        lseek(fdSrc,0,SEEK_SET);
        int n_read = read(fdSrc,&data2,sizeof(struct Test ));
        printf("read:%d,%c\n",data2.data,data2.c);

        close(fdSrc);
        return 0;
}
~

结构体数组写入文件:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
struct Test
{
        int data;
        char c;
};
int main(int argc,char **argv)
{
        int fdSrc;
        struct Test data[2] = {{100,'a'},{200,'b'}};
        struct Test data2[2];
        fdSrc = open("./file2",O_RDWR);
        int n_write  = write(fdSrc,&data,sizeof(struct Test)*2); //重新写入参数   用链表要另作算法,这是数组,读的块
        lseek(fdSrc,0,SEEK_SET);
        int n_read = read(fdSrc,&data2,sizeof(struct Test )*2);
        printf("read:%d,%c\n",data2[0].data,data2[0].c);
        printf("read:%d,%c\n",data2[1].data,data2[1].c);
        close(fdSrc);
        return 0;
}

13.标准C库对文件操作引入

总结open与fopen的区别,文章来源地址

1.来源
  • open是UNIX系统调用函数(包括LINUX等),返回的是文件描述符(File Descriptor),它是文件在文件描述符表里的索引。`

  • fopen是ANSIC标准中的C语言库函数,在不同的系统中应该调用不同的内核api。返回的是一个指向文件结构的指针。

2.移植性

fopen是C标准函数,因此拥有良好的移植性;而open是UNIX系统调用,移植性有限。

3.适用范围
  • open返回文件描述符,而文件描述符是UNIX系统下的一个重要概念,UNIX下的一切设备都是以文件的形式操作。如网络套接字、硬件设备等。当然包括操作普通正规文件(Regular File)。 (一些特定条件(进程间的通行,管道)下必须用open`打开)

  • fopen是用来操纵普通正规文件(Regular File)的

4.文件IO层次

如果从文件IO的角度来看,前者属于低级IO函数,后者属于高级IO函数。低级和高级的简单区分标准是:谁离系统内核更近。低级文件IO运行在内核态,高级文件IO运行在用户态。

5. 缓冲

1.缓冲文件系统
缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用;当执行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”,装满后再从内存“缓冲区”依此读出需要的数据。执行写文件的操作时,先将数据写入内存“缓冲区”,待内存“缓冲区”装满后再写入文件。由此可以看出,内存“缓冲区”的大小,影响着实际操作外存的次数,内存“缓冲区”越大,则操作外存的次数就少,执行速度就快、效率高。一般来说,文件“缓冲区”的大小随机器 而定。fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等。

2.非缓冲文件系统
缓冲文件系统是借助文件结构体指针来对文件进行管理,通过文件指针来对文件进行访问,既可以读写字符、字符串、格式化数据,也可以读写二进制数据。非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度快,由于ANSI标准不再包括非缓冲文件系统,因此建议大家最好不要选择它。open, close, read, write, getc, getchar, putc, putchar等。

一句话总结一下,就是open无缓冲,fopen有缓冲。前者与read, write等配合使用, 后者与fread,fwrite等配合使用。

使用fopen函数,由于在用户态下就有了缓冲,因此进行文件读写操作的时候就减少了用户态和内核态的切换(切换到内核态调用还是需要调用系统调用API:readwrite);而使用open函数,在文件读写时则每次都需要进行内核态和用户态的切换;表现为,如果顺序访问文件,fopen系列的函数要比直接调用open系列的函数快;如果随机访问文件则相反。

14.标准C库打开创建文件读写光标移动

open和fopen的区别

1.fopen函数

FOPEN(3)                  Linux Programmer's Manual                 FOPEN(3)

NAME
       fopen, fdopen, freopen - stream open functions

SYNOPSIS
       #include <stdio.h>

       FILE *fopen(const char *path, const char *mode);//常用 参数:文件地址  权限

       FILE *fdopen(int fd, const char *mode);

       FILE *freopen(const char *path, const char *mode, FILE *stream);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       fdopen(): _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE

参数说明

参数mode字符串包含了文件访问模式,欲打开的文件路径及文件名,参数 mode 字符串则代表着流形态。

mode 有下列几种形态字符串:

字符串说明
r以只读方式打开文件,该文件必须存在。
r+以读/写方式打开文件,该文件必须存在。
rb+以读/写方式打开一个二进制文件,只允许读/写数据。
rt+以读/写方式打开一个文本文件,允许读和写。
w打开只写文件,若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件。
w+打开可读/写文件,若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件。
a以附加的方式打开只写文件。若文件不存在,则会创建该文件;如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(EOF 符保留)。
a+以附加方式打开可读/写的文件。若文件不存在,则会创建该文件,如果文件存在,则写入的数据会被加到文件尾后,即文件原先的内容会被保留(EOF符不保留)。
wb以只写方式打开或新建一个二进制文件,只允许写数据。
wb+以读/写方式打开或新建一个二进制文件,允许读和写。
wt+以读/写方式打开或新建一个文本文件,允许读和写。
at+以读/写方式打开一个文本文件,允许读或在文本末追加数据。
ab+以读/写方式打开一个二进制文件,允许读或在文件末追加数据。

2.fwrite函数 & fread函数

FREAD(3)                  Linux Programmer's Manual                 FREAD(3)

NAME
       fread, fwrite - binary stream input/output

SYNOPSIS
       #include <stdio.h>

       size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);//从	FILE *stream 读内容到void *ptr

       size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);//从void *ptr读取内容写到FILE *stream
								//size_t size:大小  size_t nmemb:写几次

DESCRIPTION
       The  function  fread()  reads nmemb elements of data, each size bytes
       long, from the stream pointed to by stream, storing them at the loca‐
       tion given by ptr.

       The  function fwrite() writes nmemb elements of data, each size bytes
       long, to the stream pointed to by stream,  obtaining  them  from  the
       location given by ptr.

       For nonlocking counterparts, see unlocked_stdio(3).

3.fseek函数

使用原理和lseek类似

FSEEK(3)                  Linux Programmer's Manual                 FSEEK(3)

NAME
       fgetpos, fseek, fsetpos, ftell, rewind - reposition a stream

SYNOPSIS
       #include <stdio.h>

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

       long ftell(FILE *stream);

       void rewind(FILE *stream);

       int fgetpos(FILE *stream, fpos_t *pos);
       int fsetpos(FILE *stream, fpos_t *pos);

4.fclose函数

FCLOSE(3)                 Linux Programmer's Manual                FCLOSE(3)

NAME
       fclose - close a stream

SYNOPSIS
       #include <stdio.h>

       int fclose(FILE *fp);

DESCRIPTION
       The  fclose()  function  flushes the stream pointed to by fp (writing
       any buffered output data using fflush(3)) and closes  the  underlying
       file descriptor.

       The  behaviour of fclose() is undefined if the stream parameter is an
       illegal pointer, or is a descriptor  already  passed  to  a  previous
       invocation of fclose().

RETURN VALUE
       Upon successful completion 0 is returned.  Otherwise, EOF is returned
       and the global variable errno is  set  to  indicate  the  error.   In
       either  case  any further access (including another call to fclose())
       to the stream results in undefined behavior.

使用:

#include <stdio.h>
#include <string.h>

int main()
{
        FILE *fp;
        fp = fopen("aaaa.txt","w+");	//打开文件 
        char *p = "this is wang";
        char readbuf[128]={"\0"};
        int n_fwrite = fwrite(p,sizeof(char) * strlen(p),1,fp);	// 从p读内容写到fp
    //  int n_fwrite = fwrite(p,sizeof(char),strlen(p),fp);	// 从p读内容写到fp
        fseek(fp,0,SEEK_SET);
        int n_fread = fread(readbuf,sizeof(char) * strlen(p),1,fp);//从fp 读内容到readbuf
        printf("readbuf:%s\n",readbuf);
        fclose(fp);
        return 0;
}

15.标准C库写入结构体到文件

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
struct Test
{
	int a;
	char c;

};
int main()
{
	FILE *fp;
	
	struct Test data = {100,'a'};
	struct Test data2;

	fp = fopen("./file1","w+");

	int n_write = fwrite(&data,sizeof(struct Test),1,fp);  //n_write=1 返回的是写的次数

	fseek(fp,0,SEEK_SET);

	int n_read = fread(&data2, sizeof(struct Test),1,fp); 
	
	printf("read %d,%c \n",data2.a,data2.c);
	fclose(fp);

	return 0;
}

16.文件其他函数讲解及文件到尾

函数原型:

NAME
       fputc, fputs, putc, putchar, puts - output of characters and strings

SYNOPSIS
       #include <stdio.h>

       int fputc(int c, FILE *stream);

       int fputs(const char *s, FILE *stream);

       int putc(int c, FILE *stream);

       int putchar(int c);

       int puts(const char *s);

DESCRIPTION
       fputc() writes the character c, cast to an unsigned char, to stream.

       fputs()  writes  the  string  s to stream, without its terminating null
       byte ('\0').

       putc() is equivalent to fputc() except that it may be implemented as  a
       macro which evaluates stream more than once.

       putchar(c); is equivalent to putc(c,stdout).

       puts() writes the string s and a trailing newline to stdout.

       Calls  to the functions described here can be mixed with each other and
       with calls to other output functions from the  stdio  library  for  the
       same output stream.

       For nonlocking counterparts, see unlocked_stdio(3).

RETURN VALUE
       fputc(),  putc()  and  putchar()  return  the  character  written as an
       unsigned char cast to an int or EOF on error.

       puts() and fputs() return a nonnegative number on success,  or  EOF  on
       error.

CONFORMING TO
       C89, C99.

int feof(FILE *stream);判断是否到文件尾巴,没到尾巴返回0;到尾巴返回非0

使用:

#include <stdio.h>
#include <string.h>


int main()
{
	FILE *fp;
	int i;
	char *str = "write char inout!";
	int len = strlen(str);

	fp = fopen("./test.txt","w+");
	for(i=0;i<len;i++){
	// int fputc(int c, FILE *stream);
		fputc(*str,fp);
		str++;
	}
	fclose(fp);
	return 0;
}

#include <stdio.h>
#include <string.h>


int main()
{
	FILE *fp;
	int i;
	char c;

	fp = fopen("./test.txt","r");

	while(!feof(fp)){// nonezero if reach end of file
		
		c = fgetc(fp);
		printf("%c",c);
	}
	fclose(fp);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值