3 文件操作和时间编程
目录
3 文件操作和时间编程
一、时间编程
1、有关时间的shell命令
2、时间API
(1)获取日历时间
(2)将日历时间转化为本地时间
(3)将日历时间转化为格林威治时间
(4)将日历时间直接转化为本地时间字符串
(5)将结构体中的时间按照自己想要的格式显示
(6)将结构体中的时间转化为字符串
二、文件操作
引入
基于缓冲区的和基于非缓冲区的文件操作的区别
1、什么是缓冲区?
2、c 语言学习的文件操作 是基于缓冲区的文件操作
基于非缓冲的文件操作 低级I/O
(1)打开文件
(2)对文件进行写入
(3)对文件进行读取
(4)偏移光标
(5)关闭文件
例题:
一、时间编程
1、有关时间的shell命令
-- data
- 查看本地时间的指令
-- cal
- 查看日历
2、时间API
(1)获取日历时间
-- 日历时间:从 1970.1.1 0:0:0 至现在的一个秒数
-- 函数的头文件
- #include <time.h>
-- 函数的原型
- time_t time(time_t *tloc);
-- 函数的作用:
- 获取日历时间 从 1970.1.1 0:0:0 至现在的一个秒数
-- 函数的参数:
- time_t *tloc:
-- 获取日历时间的秒数有两种方法
- (1)传入参数为NULL 空 该参数无用,从返回值中获取秒数
- (2)传入参数是一个同等类型的地址 会将日历时间放到这个地址中去
-- 函数的返回值:
- 成功返回: 秒数
- 失败返回: -1
(2)将日历时间转化为本地时间
-- 函数头文件
- #inlcude <time.h>
-- 函数原型
- struct tm *localtime(const time_t *timep);
-- 函数的作用:
- 将日历时间转化为本地时间结构体
-- 函数的参数:
- timep:填写保存日历时间的地址
-- 填写保存 time 函数获取的日历时间的变量的地址
-- 函数的返回值:
- 成功返回: 结构体指针
- 失败返回: NULL
(3)将日历时间转化为格林威治时间
-- 相差8个小时
-- 函数头文件
- #include <time.h>
-- 函数原型
- struct tm *gmtime(const time_t *timep);
-- 函数的作用:
- 通过日历时间获取格林威治时间
-- 函数的参数:
- timep:存放日历时间的地址
- 填写保存 time 函数获取的日历时间的变量的地址
-- 函数的返回值: 成功返回 地址
-- 失败返回 NULL
(4)将日历时间直接转化为本地时间字符串
-- 函数头文件
- #include <time.h>
-- 函数原型
- char *ctime(const time_t *timep);
-- 函数的作用:
- 将日历时间直接转化为本地时间字符串
-- 函数的参数:
- timep:存放日历时间的地址 -- 填写保存 time 函数获取的日历时间的变量的地址
-- 函数的返回值:
- 成功返回 指向字符串的首地址
- 失败返回 NULL
(5)将结构体中的时间按照自己想要的格式显示
-- 函数头文件
- #include <time.h>
-- 函数原型
- size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
-- 函数功能:
- 将结构体中的时间按照 format 中的参数进行显示
-- 函数的参数:
- s:指向用来存放格式化好之后的时间字符串 -- 填写一个 char 类型的数组的首地址
- max:第一个参数指向的数组的大小
- format:填写自己想要的时间格式
-- %F 年-月-日
-- %T --时间,等于%H:%M:%S - struct tm *tm: 填写 localtime 的返回值
-- 函数的返回值:
- 成功返回向数组中放了多少个字节
- 超过数组大小也返回 0
- 失败返回 0
(6)将结构体中的时间转化为字符串
-- 函数头文件
- #include <time.h>
-- 函数原型
- char *asctime(const struct tm *tm);
-- 函数的作用:
- 将结构体中的时间转化为字符串
-- 函数的参数:
- struct tm *tm:填写 localtime 的返回值
- 填写 gmtime 的返回值
-- 函数的返回值:
- 成功 返回 字符串首地址
- 失败 返回 NULL
二、文件操作
引入
-- 1)文件:
- linux 系统有一个十分重要特点:
- linux 下一切皆是文件
-- 2)文件分类:
- 七种 - 普通 d 目录 c 字符 s 套节字
- p 管道 b 块设备 l 链接
-- 3)文件操作:
- C 语言学习的文件操作 是高级 IO
-- 基于缓冲区的文件操作 - linux 下的文件操作 是低级 IO
-- 基于非缓冲区的文件操作
-- 实时性高 - -- 4)文件操作流程:
- 打开-->写入 or 读取-->关闭
基于缓冲区的和基于非缓冲区的文件操作的区别
-- 基于缓冲区的文件操作会将数据先存入缓冲区,直到达到将缓冲区的内容输出的条件,才会将缓冲区的内容输出到文件中
-- 基于非缓冲区的文件操作会将数据直接写入文件中,不经过缓冲区,但是就需要每次输出都要调用cpu,所以效率较低。 -- 实时
1、什么是缓冲区?
-
缓冲区又称为缓存,是内存空间的一部分。也就是说,计算机在内存中预留了一定的存储空间,用来暂时保存输入或输出的数据,这部分预留的空间就叫做缓冲区。例如:scanf函数。
-
有时候,从键盘输入的内容,或者将要输出到显示器上的内容,会暂时进入缓冲区,待时机成熟,再一股脑将缓冲区中的所有内容“倒出”,我们才能看到变量的值被刷新,或者屏幕产生变化。
2、c 语言学习的文件操作 是基于缓冲区的文件操作
-- 输入 输出都有缓冲区
-- 缓冲区的输出条件
- 1 \n
- 2 程序正常结束
- 3 满了 缓冲区的大小为 1024 字节
- 4 fflush()函数
基于非缓冲的文件操作 低级I/O
(1)打开文件
-- 函数头文件
- #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);
-- 函数的作用:
- 根据函数的参数打开文件并获取文件描述符
-- 函数的参数:
- pathname:填写要打开的文件的路径名
- flags:
-- O_RDONLY 只读
-- O_WRONLY 只写
-- O_RDWR 读写
注:flags 中的参数可以通过 或符号‘|’ 来使用多个选项,前面三个必须有其一
-- O_TRUNC 清空文件内容
-- O_APPEND 追加
-- O_CREAT 创建文件
注:如果使用了 O_CREAT 这个选项 open 函数需要第三个参数
例:O_RDONLY | O_APPEND | O_TRUNC | O_CREAT
-- mode:创建出来的文件权限0777 0664 等
实际创建的文件权限值为:(mode & ~umask) umask 的值为 0002
0777 &~0002
0777 & 0775 = 0775
-- 函数的返回值: - 成功返回 打开文件对应的文件描述符
- 失败返回 -1
注:文件描述符从 3 开始
因为 0 1 2 已经有文件打开过了
- 0:标准输入
- 1:标准输出
- 2:标准错误
-- 每使用 open 打开一个文件都会让文件描述符+1
注:文件描述符就代表这个文件,如3就代表3.c
(2)对文件进行写入
-- 函数头文件
- #include <unistd.h>
-- 函数原型
- ssize_t write(int fd, const void *buf, size_t count);
-- 函数的作用:
- 根据传入的文件描述符进行数据的写入
-- 函数的参数
- fd:要进行写入数据的文件描述符
- buf:要进行数据写入的首地址
- count:要写入多少字节
-- 函数的返回值:
- 成功 返回实际写入的字节数
- 失败 返回-1
(3)对文件进行读取
-- 函数头文件
- #include <unistd.h>
-- 函数原型
- ssize_t read(int fd, void *buf, size_t count);
-- 函数的作用:
- 从文件描述符中进行数据的读取
-- 函数的参数:
- fd:要进行读取的文件描述符 打开文件的时候需要读权限
- buf:用来存放数据的地址
- count:读取多少个字节
-- 函数的返回值:
- 成功返回 实际读取到的字节数
- 失败返回 -1
-- 如果实际读取的字节数小于我们所需的字节数,说明我们读取到文件末尾了
-- 返回值为 0 表示光标在文件末尾
(4)偏移光标
-- 函数头文件
- #include <sys/types.h>
- #include <unistd.h>
-- 函数原型
- off_t lseek(int fd, off_t offset, int whence);
-- 函数的作用:
- 根据文件描述符和参数进行光标的偏移
-- 函数的参数:
- fd:要进行偏移光标的文件描述符
- offset:偏移量
- whence:SEEK_SET 文件开头
- SEEK_CUR 当前位置
- SEEK_END 文件结尾
-- 函数返回值:
- 成功返回 偏移后光标距离文件开头的字节数
- 失败返回 -1
(5)关闭文件
-- 函数头文件
- #include <unistd.h>
-- 函数原型
- int close(int fd);
-- 函数的作用:
- 关闭文件
-- 函数的参数:
- fd:要进行关闭的文件描述符
-- 函数的返回值:
- 成功返回 0
- 失败返回 -1
例题:
-- 通过主函数传参 实现 cp 功能
- ./a.out 1.c 2.c
- 把 1.c 的内容复制给 2.c
-- 提示:
- 通过 open 函数来打开 1.c 和 2.c
- 如果 1.c 不存在 就是无法复制 ---程序结束
- 存在 读打开 打开 2.c 创建|清空 写
- 循环从 1.c 中读取内容 复制到 2.c 中
- 直到 1.c 文件尾 关闭两个文件
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define SIZE 4096
int main(int argc, char const *argv[])
{
if(argc<3)
{
printf("缺少参数,请输入参数!\n");
return -1;
}
int fd1 = open(argv[1],O_RDONLY);
if(fd1 == -1)
{
perror("open");
printf("%s 文件不存在,无法复制!\n",argv[1]);
return -1;
}
int fd2 = open(argv[2],O_RDWR |O_TRUNC|O_CREAT,0664);
char a[SIZE];
//lseek(fd2, 0, SEEK_SET);
ssize_t num = 0;
while(1)
{
num = read(fd1, a, sizeof(a));
write(fd2, a, num);
if(num<1024)
break;
}
close (fd1);
close (fd2);
printf("复制成功!\n");
return 0;
}