目录
一、知识铺垫
二、回首一下之前C语言的文件操作,并对比重定向
1、w选项与输出重定向(>)
2、a选项与追加重定向(>>)
3、熟悉一下读写操作
4、练习读操作:
三、什么叫做当前路径?当前路径与文件创建的关系?
四、访问文件的系统调用
1、步调默认打开的文件流
编辑
2、常见的读写函数:
3、open系统调用:
4、一个小细节:用位图传参:
5、open参数解析:
6、写文件的系统调用:write
7、关闭文件的系统调用:close
五、文件形貌符(fd)
1、认识文件形貌符
2、文件形貌符具体是什么?为什么后续访问文件的系统调用都要通过fd来操作?
3、一切皆文件
4、文件形貌符表的分配规则以及利用规则实现重定向
(1)文件形貌符表的分配规则
(2)改变重定向的系统调用(dup2)
(3)dup2利用场景
5、给自界说shell增长重定向功能
六、缓冲区题目:
1、简单先容
2、为什么利用缓冲区能提高服从?
3、缓冲区在哪里?
4、用代码证实缓冲区的存在
七、模拟实现文件操作的常用接口(有缓冲区和无缓冲区版本)
1、无缓冲区版本
mystdio.h
mystdio.c
filetest.c
2、有缓冲区版本
mystdio.c
mystdio.h
filetest.c
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,不由得分享一下给大家
点击跳转到网站
一、知识铺垫
(1)文件 = 内容 + 属性
(2)访问文件之前,都得先打开该文件。修改文件都是通过实行代码的方式完成修改。
(3)打开文件条件要文件必须加载到内存中
(4)由谁打开文件?历程打开文件。
(5)一个历程可以打开多少文件?可以打开多个文件
(6)一定时间内,系统中会存在多个历程,也大概同时存在更多的被打开文件,OS要不要管理多个被历程打开的文件呐?答案是肯定要管理的。如何管理呐?答案是先形貌在构造。
(所以内核中一定要有形貌被打开文件的结构体,并用其界说对象)。
(7)历程和文件的关系:结构体之间的关系,struct task_struct 和 struct XXX
(8)系统中是不是所有的文件都被历程打开了?答案是:并不是,那些没有被打开的文件是被存储磁盘中的,所以也叫磁盘文件。
二、回首一下之前C语言的文件操作,并对比重定向
- #include<stdio.h>
- int main()
- {
- FILE *fp = fopen("./log.txt","w");
- if(fp == NULL)
- {
- perror("fopen");
- return 1;
- }
- const char* str = "hello file\n";
- fputs(str,fp);
- fclose(fp);
- return 0;
- }
复制代码
1、w选项与输出重定向(>)
以" w "选项打开文件,是对文件进行写操作,但是打开前会将文件原有内容清空。而重定向(" > ")也是会将文件原有内容清空,由于重定向之前需要将文件打开,而打开这个操作就会将文件内容清空:
2、a选项与追加重定向(>>)
fopen以"a"选项打开文件,是追加的方式进行写,即在文件原有内容的末尾接着写,这与追加重定向功能一样:
- #include<stdio.h>
- int main()
- {
- FILE *fp = fopen("./log.txt","a");
- if(fp == NULL)
- {
- perror("fopen");
- return 1;
- }
- const char* str = "hello file\n";
- fputs(str,fp);
- fclose(fp);
- return 0;
- }
复制代码
还有其他选项可以查手册。
3、熟悉一下读写操作
- #include<stdio.h>
- #include<string.h>
- #define FILENAME "log.txt"
- //练习读写操作
- int main()
- {
- FILE* fp = fopen(FILENAME,"w");
- if(fp == NULL)
- {
- perror("fopen");
- return 1;
- }
- const char* msg = "hello HF";
- int cnt = 6;
- while(cnt)
- {
- int n = fwrite(msg,strlen(msg),1,fp);
- printf("write %d block\n",n);
- cnt--;
- }
- fclose(fp);
- return 0;
- }
复制代码
4、练习读操作:
- #include<stdio.h>
- #include<string.h>
- #include<unistd.h>
- #include<sys/types.h>
- #define FILENAME "log.txt"
- //练习读
- int main()
- {
- FILE* fp = fopen(FILENAME,"r");
- if(fp == NULL)
- {
- perror("fopen");
- return 1;
- }
- char buffer[64];
- while(1)
- {
- char* r = fgets(buffer,sizeof(buffer),fp);
- if(!r) break;//返回NULL则终止读
- printf("%s\n",buffer);
- }
- return 0;
- }
复制代码
三、什么叫做当前路径?当前路径与文件创建的关系?
当前路径指历程启动时地点的工作目录。历程启动时,会自动记录自己启动时的地点的目录,可通过指令查看:(ls /proc/历程pid -l)
当前路径与文件创建的关系:从前都以为文件是默认创建在可实行步调的同级目录,实则不然,文件是默认创建在历程的工作目录下。
如果我们在创建文件之前,修改历程的工作目录,那么文件也会创建到修改后的工作目录下:
修改历程的工作目录的接口:
参数就是要修改的工作目录。
- #include<stdio.h>
- #include<string.h>
- #include<unistd.h>
- #include<sys/types.h>
- #define FILENAME "HF.txt"
- //修改进程的工作目录
- int main()
- {
- int i = chdir("/root/study/linux-learning");
- if(i)
- {
- printf("转换失败\n");
- }
- FILE* fp = fopen(FILENAME,"w");
- if(fp == NULL)
- {
- perror("fopen");
- return 1;
- }
- const char* msg = "hello HF";
- int cnt = 6;
- while(cnt)
- {
- int n = fwrite(msg,strlen(msg),1,fp);
- printf("write %d block\n",n);
- cnt--;
- }
- fclose(fp);
- return 0;
- }
复制代码
四、访问文件的系统调用
1、步调默认打开的文件流
2、常见的读写函数:
- #include<stdio.h>
- #include<string.h>
- #include<unistd.h>
- #include<sys/types.h>
- #define FILENAME "log.txt"
- //常见的写函数
- int main()
- {
- printf("hello printf\n");
- fprintf(stdout,"hello fprintf\n");//将数据输出到标准输出中(stdout显示器设备);
- fputs("hello fputs\n",stdout);//也是将数据输出到标准输出中,但不能像fprintf那样支持格式化输出
- const char* msg = "hello fwrite\n";
- fwrite(msg,1,strlen(msg),stdout);
- return 0;
- }
复制代码- #include<stdio.h>
- #include<string.h>
- #include<unistd.h>
- #include<sys/types.h>
- #define FILENAME "log.txt"
- int main()
- {
- //fscanf
- char buffer[64];
- fscanf(stdin,"%s",buffer);//从标准输出(键盘)中读取数据放到buffer中,空格和换行符作为分隔符
- printf("%s\n",buffer);
- return 0;
- }
复制代码 3、open系统调用:
访问文件不仅仅有C语言的文件接口,OS还必须提供对应的访问文件的系统调用,就是open系列的系统调用:
4、一个小细节:用位图传参:
- #include<stdio.h>
- #include<string.h>
- #include<unistd.h>
- #include<sys/types.h>
- #define FILENAME "log.txt"
- //用位图传参
- #define ONE 1
- #define TWO (1<<1)
- #define THREE (1<<2)
- #define FOUR (1<<3)
- #define FIVE (1<<4)
- void myPrint(int flag)
- {
- if(flag & ONE) printf("1");
- if(flag & TWO) printf("2");
- if(flag & THREE) printf("3");
- if(flag & FOUR) printf("4");
- if(flag & FIVE) printf("5");
- printf("\n");
- }
- int main()
- {
- myPrint(ONE);
- myPrint(TWO);
- myPrint(ONE | TWO);
- myPrint(THREE | FOUR | FIVE);
- myPrint(FIVE);
- return 0;
- }
复制代码
5、open参数解析:
(1)参数一:pathname,是要打开大概创建的文件路径名(绝对路径/相对路径)
(2)参数二:flags,标记位,表现打开文件的方式,具体值是宏界说(可查看手册),传参方式类似于第4点的位图传参方式,可以通过按位或(|)设置多个标记。
注意:利用这些标记位需要包罗头文件:<fcntl.h>
三个根本标记位:
标记作用O_RDONLY只能读取,不能写入,若进行写操作会返回 EBADF 错误O_WRONLY只能写入,不能读取,需配合 O_CREAT 创建新文件O_RDWR可同时读取和写入,写入大概覆盖原有内容,需控制偏移量 其他标记如下:
标记作用O_CREAT如果文件不存在,则创建它(需配合第三个参数 mode 利用)。O_EXCL与 O_CREAT 联用,若文件已存在则返回错误(可用于避免文件被不测覆盖)。O_TRUNC若文件存在且为可写模式,将其长度截断为 0(即打开文件前先清空文件内容)。O_APPEND追加写,写入时始终追加到文件末尾(自动将文件偏移量设置到文件末尾)。O_NONBLOCK以非壅闭模式打开文件(用于 I/O 多路复用,如网络编程)。 (3)参数三:mode,用于指定新建文件的权限,仅当利用 O_CREAT 或 O_TMPFILE 标记时生效。偶然间,如果不指定mode参数,那么创建的文件的权限大概会乱码:
- #include<stdio.h>
- #include<string.h>
- #include<unistd.h>
- #include<sys/types.h>
- #include<fcntl.h>
- #define FILENAME "log.txt"
- //使用open
- int main()
- {
- int fd = open("HF.txt",O_WRONLY | O_CREAT);
- if(fd == -1)
- {
- perror("open");
- return 1;
- }
- return 0;
- }
复制代码
如图会发现创建的文件的权限位乱码的,所以此时我们需要利用第三个参数code解决:
但受系统权限掩码的限定,会导致创建的文件的权限与我们设置的权限不一样,此时需要提前利用一个系统调用:umask(0),头文件: <sys/stat.h>
表明:用于设置当前历程的文件创建掩码(file creation mask)为 0。文件创建掩码是一个位掩码,用于在创建文件或目录时屏蔽某些权限位,从而控制新创建文件的默认权限。
此时就与我们设置的权限一样了。
6、写文件的系统调用:write
参数解析:
参数名称数据范例形貌fdint文件形貌符,指向已打开的文件、管道、套接字或设备(如标准输入stdin对应 fd = 0;标准输出stdout对应 fd = 1;标准错误stderr对应 fd = 2)。
通过open系统调用获取,用于标识写入目标。bufconst void *写入缓冲区指针,它是一个指向用户空间缓冲区的指针,这个缓冲区里存储着准备写入的数据。数据的传输方向是从 用户空间(buf)到内核空间(fd 对应的设备或文件)。
可以是字符数组、结构体或其他数据范例,需确保内存访问权限合法。countsize_t要写入的字节数,指定从buf中读取的最大数据量。
实际写入字节数大概小于count(如碰到文件末尾、磁盘空间不足或权限限定)。 - #include<stdio.h>
- #include<string.h>
- #include<unistd.h>
- #include<sys/types.h>
- #include<fcntl.h>
- #include<sys/stat.h>
- #define FILENAME "log.txt"
- int main()
- {
- umask(0);
- int fd = open("HF.txt",O_WRONLY | O_CREAT,0666);
- const char* str = "hello write\n";
- write(fd,str,strlen(str));
- return 0;
- }
复制代码
注意:
7、关闭文件的系统调用:close
五、文件形貌符(fd)
1、认识文件形貌符
这是一个及其重要的概念,文件形貌符也就是open函数的返回值,我们先看看值是什么?
- #include<stdio.h>
- #include<string.h>
- #include<unistd.h>
- #include<sys/types.h>
- #include<fcntl.h>
- #include<sys/stat.h>
- #define FILENAME "log.txt"
- //认识文件描述符
- int main()
- {
- int fd1 = open("HF1.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);
- int fd2 = open("HF2.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);
- int fd3 = open("HF3.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);
- int fd4 = open("HF4.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);
- int fd5 = open("HF5.txt",O_WRONLY | O_CREAT | O_TRUNC,0666);
- printf("fd1:%d\n",fd1);
- printf("fd2:%d\n",fd2);
- printf("fd3:%d\n",fd3);
- printf("fd4:%d\n",fd4);
- printf("fd5:%d\n",fd5);
- return 0;
- }
复制代码
可以看到值其实就是整形,但为什么是从3开始呐?
由于0,1,2端口已经默认被三个标准占用了:
标准输入(stdin):0
标准输出(stdout):1
标准错误(stderr):2
由上述知识我们可以知道,C语言的相干文件接口,本质就是封装了各个系统调用,重要是为了保证自己的跨平台性。
2、文件形貌符具体是什么?为什么后续访问文件的系统调用都要通过fd来操作?
上面我们知道,历程要管理打开的文件需要先形貌后构造。
(1)起首task_struct中存在一个成员变量(struct file_struct *files),这个成员指向的结构体(struct file_struct)里面存在一个成员,该成员表现历程打开的文件形貌符表。
(2)所谓文件形貌符表也就是一个数组,其数组范例为(struct file** fd_array[ ]),这是一个二级指针,其内容的范例为(struct file*)
(3)struct file是文件结构体,里面包罗了文件属性、方法集、文件运行时的状态信息、操作函数和资源引用等等信息(如下图),被称为文件操作的 “控制器”。
(4)而open返回值fd(文件形貌符)就是这个文件形貌符表的下标,有了这个下标,我们就可以找到下标对应的struct file,从而就可以操作这个文件,所以后续访问文件的系统调用都要通过fd来操作的。
3、一切皆文件
4、文件形貌符表的分配规则以及利用规则实现重定向
(1)文件形貌符表的分配规则
文件形貌符表的分配规则:会叫最小的没有被利用的下标,分配给最新打开的文件。
输出重定向的现象:
(2)改变重定向的系统调用(dup2)
我们先学习dup2系统调用,参数解析如下:
(1)oldfd:已存在的、有效的文件形貌符,指向一个已打开的文件、设备或套接字。
| 若 oldfd 无效(如未打开或已关闭),dup2() 返回 -1 并设置 errno=EBADF |
(2)newfd:新绑定的文件形貌符,dup2() 会将文件对象从前的文件形貌符oldfd解绑,然后与 newfd进行绑定。
若 newfd 未打开:
直接将 newfd 指向 oldfd 对应的 struct file 对象。 | 若 newfd 已打开:
先关闭 newfd(减少其原 struct file 的引用计数),再复制 oldfd 的文件对象到 newfd。
| 若 newfd == oldfd:
不实行任何操作,直接返回 newfd(避免自我关闭)。
| (3)dup2利用场景
重定向到文件:
- //使用dup2
- int main()
- {
- int fd = open("newfile",O_WRONLY|O_CREAT|O_TRUNC,0666);
- dup2(fd,1);//将newfile文件与标准输出进行绑定
- //这样printf就会默认向上述文件进行输出
- printf("hello newfile\n");
- return 0;
- }
复制代码
从文件读取内容到数组:
- int main()
- {
- int fd = open("newfile",O_RDONLY,0666);
- dup2(fd,0);//将文件的文件描述符与标准输出进行绑定
- char buffer[1024];
- while(1)
- {
- //默认情况,stdin会从键盘中读取,若键盘不输入,是会发生阻塞的
- char* s = fgets(buffer,sizeof(buffer),stdin);//此时stdin会默认从文件中读取
- if(s==NULL)break;
- printf("file content:%s",buffer);
- }
- return 0;
- }
复制代码
5、给自界说shell增长重定向功能
六、缓冲区题目:
1、简单先容
缓冲区其实是一块内存区域,目的是用来提高利用者的服从(空间换时间)。
比如从云南到北京运送货品,总共需要运送100kg,如果一次运送10kg,需要来回10次,如许耗费的时间就非常多;如果我用比较大的运输机一次就能运送100kg,如许就用运送一次,大大提高了服从。
2、为什么利用缓冲区能提高服从?
注意:平时我们所说的,包括这里即将减少的缓冲区都是语言层面的缓冲区(比如C语言里面的缓冲区),与OS内核中的缓冲区没有关系。
为什么利用语言层面的缓冲区能提高服从?
结合上述运送物资的例子,我们知道通过系统调用访问OS是需要有很大开销的,如果我们语言层面不设置缓冲区,那么来一点数据就送给OS,又来一点数据又会访问OS,如许就会多出很多开销,但如果我们在语言层设置一个缓冲区,让需要存储的数据线一点一点累积保存到缓冲区,达到一定的空间后,我们一次性传输给OS,如许访问OS的次数就大大减少了,从而就提高了服从。
3、缓冲区在哪里?
缓冲区是在FILE结构体中,也就是由FILE结构体来维护缓冲区:
缓冲区常见字段:
- struct _IO_FILE {
- // 基础文件描述符
- int _fileno;
-
- // 缓冲区指针与状态
- char* _IO_read_ptr; // 读缓冲区当前位置
- char* _IO_read_end; // 读缓冲区结束位置
- char* _IO_read_base; // 读缓冲区起始位置
-
- char* _IO_write_base; // 写缓冲区起始位置
- char* _IO_write_ptr; // 写缓冲区当前位置
- char* _IO_write_end; // 写缓冲区结束位置
- char* _IO_buf_base; // 缓冲区基址
- char* _IO_buf_end; // 缓冲区结束地址
-
- // 缓冲区状态标志
- int _IO_write_base; // 写缓冲区起始位置(重复字段,实际为标志位)
- unsigned _flags; // 缓冲区标志(如是否全缓冲、行缓冲等)
- unsigned _IO_file_flags; // 文件状态标志
-
- // 缓冲区大小与类型
- int _IO_buf_size; // 缓冲区大小
- int _mode; // 读写模式
-
- // ... 其他字段(省略)
- };
复制代码 核心字段:
4、用代码证实缓冲区的存在
- //证明缓冲区的存在
- int main()
- {
- //使用系统调用
- const char* s1 = "hello write\n";
- write(1,s1,strlen(s1));
- //使用C语言接口
- const char* s2 = "hello fprintf\n";
- fprintf(stdout,"%s",s2);
- const char* s3 = "hello fwrite\n";
- fwrite(s3,strlen(s3),1,stdout);
- fork();
- return 0;
- }
复制代码 如果我们直接运行那么就会正常打印,由于表现器是行刷新(即写完一行就刷新数据(\n))
但如果我们重定向到某个文件,会发现一个奇怪的现象:
C语言接口的内容会存在两份,而系统调用的接口内容只有一份
由于我们利用了重定向,重定向的刷新策略是全缓存刷新(即缓冲区满了才刷新数据),但很显然代码中的两条内容是塞不满缓冲区的,所以此时会一直等待,末了会碰到fork创建子历程,而刷新数据也属于修改数据的一种方式,父子历程中恣意一个历程修改共享数据时,都会进行写实拷贝,末了历程结束,缓冲区强迫刷新,父子历程都会向文件中刷新数据,所以C语言接口的数据会存在两份,而系统调用接口write会直接将内容存在系统内部的缓冲区,此时内容与父子历程无关,所以只有一份数据。
其次printf、scanf等等函数的格式化输出也与缓冲区有关,可以搜刮相识相识。
七、模拟实现文件操作的常用接口(有缓冲区和无缓冲区版本)
1、无缓冲区版本
mystdio.h
- #pragma once
- #include<stdio.h>
- typedef struct _myFILE
- {
- int fileno;
- }myFILE;
- myFILE* my_fopen(const char* pathname,const char* mode);
- int my_fwrite(myFILE* fp,const char* fs,int size);
- //int my_fread();
- void my_fclose(myFILE* fp);
复制代码 mystdio.c
- #include "mystdio.h"
- #include <string.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <unistd.h>
- myFILE *my_fopen(const char *pathname, const char *mode)
- {
- int flag = 0;
- if (strcmp(mode, "r") == 0)
- {
- flag |= O_RDONLY;
- }
- else if (strcmp(mode, "w") == 0)
- {
- flag |= (O_CREAT | O_WRONLY | O_TRUNC);
- }
- else if (strcmp(mode, "a") == 0)
- {
- flag |= (O_CREAT | O_WRONLY | O_APPEND);
- }
- else
- {
- return NULL;
- }
- int fd = 0;
- if (flag & O_WRONLY)
- {
- umask(0);
- fd = open(pathname, flag, 0666);
- }
- else
- {
- fd = open(pathname, flag);
- }
- if (fd < 0)
- return NULL;
- myFILE *fp = (myFILE *)malloc(sizeof(myFILE));
- if (fp == NULL)
- return NULL;
- fp->fileno = fd;
- return fp;
- }
- int my_fwrite(myFILE* fp,const char* s,int size)
- {
- return write(fp->fileno,s,size);
- }
- void my_fclose(myFILE* fp)
- {
- close(fp->fileno);
- free(fp);
- }
复制代码 filetest.c
- #include"mystdio.h"
- #include<string.h>
- const char* filename = "./log.txt";
- int main()
- {
- myFILE* fp = my_fopen(filename,"w");
- if(fp == NULL) return 1;
- const char* s = "hello myflie\n";
- my_fwrite(fp,s,strlen(s));
- my_fclose(fp);
- return 0;
- }
复制代码 2、有缓冲区版本
mystdio.c
- #include "mystdio.h"
- #include <string.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <unistd.h>
- myFILE *my_fopen(const char *pathname, const char *mode)
- {
- int flag = 0;
- if (strcmp(mode, "r") == 0)
- {
- flag |= O_RDONLY;
- }
- else if (strcmp(mode, "w") == 0)
- {
- flag |= (O_CREAT | O_WRONLY | O_TRUNC);
- }
- else if (strcmp(mode, "a") == 0)
- {
- flag |= (O_CREAT | O_WRONLY | O_APPEND);
- }
- else
- {
- return NULL;
- }
- int fd = 0;
- if (flag & O_WRONLY)
- {
- umask(0);
- fd = open(pathname, flag, 0666);
- }
- else
- {
- fd = open(pathname, flag);
- }
- if (fd < 0)
- return NULL;
- myFILE *fp = (myFILE *)malloc(sizeof(myFILE));
- if (fp == NULL)
- return NULL;
- fp->fileno = fd;
- fp->cap = SIZE;
- fp->pos = 0;
- fp->flush_mode = LINE_FLUSH;
- return fp;
- }
- void my_fflush(myFILE* fp)
- {
- if(fp->pos == 0) return;
- write(fp->fileno,fp->outbuffer,fp->pos);
- fp->pos = 0;
- }
- int my_fwrite(myFILE* fp,const char* s,int size)
- {
- //向缓冲区写入
- memcpy(fp->outbuffer+fp->pos,s,size);
- fp->pos += size;
- if((fp->flush_mode & LINE_FLUSH) && fp->outbuffer[fp->pos-1] == '\n')
- {
- my_fflush(fp);
- }
- else if((fp->flush_mode & LINE_FLUSH)&&fp->pos == fp->cap)
- {
- my_fflush(fp);
- }
- return size;
- //return write(fp->fileno,s,size);
- }
- const char* toString(int flag)
- {
- if(flag & NONE_FLUSH) return "None";
- else if(flag & LINE_FLUSH)return "Line";
- else if(flag & FULL_FLUSH)return "FULL";
- return "err";
- }
- void DebugPrint(myFILE* fp)
- {
- printf("outbuffer:%s\n",fp->outbuffer);
- printf("fd:%d\npos:%d\ncap:%d\nflush_node:%s\n",fp->fileno,fp->pos,fp->cap,toString(fp->flush_mode));
- }
- void my_fclose(myFILE* fp)
- {
- my_fflush(fp);
- close(fp->fileno);
- free(fp);
- }
复制代码 mystdio.h
- #pragma once
- #include<stdio.h>
- #define SIZE 4096//缓冲区大小
- #define NONE_FLUSH (1<<1)//无自动刷新
- #define LINE_FLUSH (1<<2)//行刷新
- #define FULL_FLUSH (1<<3)//全刷新
- typedef struct _myFILE
- {
- //char inbuffer[];
- char outbuffer[SIZE];
- int pos;
- int cap;
- int flush_mode;
- int fileno;
- }myFILE;
- myFILE* my_fopen(const char* pathname,const char* mode);
- int my_fwrite(myFILE* fp,const char* fs,int size);
- //int my_fread();
- void my_fflush(myFILE* fp);
- void DebugPrint(myFILE* fp);
- void my_fclose(myFILE* fp);
复制代码 filetest.c
- #include "mystdio.h"
- #include <string.h>
- #include <unistd.h>
- const char *filename = "./log.txt";
- int main()
- {
- myFILE *fp = my_fopen(filename, "w");
- if (fp == NULL)
- return 1;
- int cnt = 5;
- char buffer[64];
- while (cnt)
- {
- snprintf(buffer, sizeof(buffer), "helloworld,hellobit,cnt:%d", cnt--);
- my_fwrite(fp, buffer, strlen(buffer));
- DebugPrint(fp);
- sleep(2);
- }
- my_fclose(fp);
- return 0;
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |