系统编程-文件操作和时间编程

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

  • 查看本地时间的指令

    alt text

-- cal

  • 查看日历

    alt text

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

alt text

(2)将日历时间转化为本地时间

-- 函数头文件

  • #inlcude <time.h>

-- 函数原型

  • struct tm *localtime(const time_t *timep);

-- 函数的作用:

  • 将日历时间转化为本地时间结构体

-- 函数的参数:

  • timep:填写保存日历时间的地址
    -- 填写保存 time 函数获取的日历时间的变量的地址

-- 函数的返回值:

  • 成功返回: 结构体指针 

    alt text

  • 失败返回: NULL

alt text

(3)将日历时间转化为格林威治时间

-- 相差8个小时

-- 函数头文件

  • #include <time.h>

-- 函数原型

  • struct tm *gmtime(const time_t *timep);

-- 函数的作用:

  • 通过日历时间获取格林威治时间

-- 函数的参数:

  • timep:存放日历时间的地址
  • 填写保存 time 函数获取的日历时间的变量的地址

-- 函数的返回值: 成功返回 地址

-- 失败返回 NULL

alt text

(4)将日历时间直接转化为本地时间字符串

-- 函数头文件

  • #include <time.h>

-- 函数原型

  • char *ctime(const time_t *timep);

-- 函数的作用:

  • 将日历时间直接转化为本地时间字符串

-- 函数的参数:

  • timep:存放日历时间的地址 -- 填写保存 time 函数获取的日历时间的变量的地址

-- 函数的返回值:

  • 成功返回 指向字符串的首地址
  • 失败返回 NULL

alt text

(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

    alt text

  • struct tm *tm: 填写 localtime 的返回值

-- 函数的返回值:

  • 成功返回向数组中放了多少个字节
  • 超过数组大小也返回 0
  • 失败返回 0

alt text

(6)将结构体中的时间转化为字符串

-- 函数头文件

  • #include <time.h>

-- 函数原型

  • char *asctime(const struct tm *tm);

-- 函数的作用:

  • 将结构体中的时间转化为字符串

-- 函数的参数:

  • struct tm *tm:填写 localtime 的返回值
  • 填写 gmtime 的返回值

-- 函数的返回值:

  • 成功 返回 字符串首地址
  • 失败 返回 NULL

alt text

二、文件操作

引入

-- 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()函数

alt text

alt text

alt text

alt text

alt text

alt text

基于非缓冲的文件操作 低级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 

    alt text

注:文件描述符从 3 开始
因为 0 1 2 已经有文件打开过了

  • 0:标准输入
  • 1:标准输出
  • 2:标准错误
    -- 每使用 open 打开一个文件都会让文件描述符+1

alt text

:文件描述符就代表这个文件,如3就代表3.c

(2)对文件进行写入

-- 函数头文件

  • #include <unistd.h>

-- 函数原型

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

-- 函数的作用:

  • 根据传入的文件描述符进行数据的写入

-- 函数的参数

  • fd:要进行写入数据的文件描述符
  • buf:要进行数据写入的首地址
  • count:要写入多少字节

-- 函数的返回值:

  • 成功 返回实际写入的字节数
  • 失败 返回-1

alt text

(3)对文件进行读取

-- 函数头文件

  • #include <unistd.h>

-- 函数原型

  • ssize_t read(int fd, void *buf, size_t count);

-- 函数的作用:

  • 从文件描述符中进行数据的读取

-- 函数的参数:

  • fd:要进行读取的文件描述符 打开文件的时候需要读权限
  • buf:用来存放数据的地址
  • count:读取多少个字节

-- 函数的返回值:

  • 成功返回 实际读取到的字节数
  • 失败返回 -1
    -- 如果实际读取的字节数小于我们所需的字节数,说明我们读取到文件末尾了
    -- 返回值为 0 表示光标在文件末尾

alt text

(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;
}

alt text

alt text

  • 17
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值