Linux 学习记录21(IO篇)

Linux 学习记录21(IO篇)

在这里插入图片描述

本文目录

  • Linux 学习记录21(IO篇)
  • 关于时间的操作
  • 一、格式化控制相关的函数
    • 1. sprintf函数
    • 2. snprintf函数
    • 3. fprintf函数
    • 4. fscanf函数
  • 二、fread、fwrite函数的使用
    • 1. fread
    • 2. fwrite
    • 3. 结构体的读写
      • (1. 写
      • (2. 读
  • 三、feof、ferror的使用
    • 1. feof
    • 2. ferror
  • 思维导图
  • 练习
    • 1. 获取系统时间,并将系统时间写入文件中,实现现象
    • 2. 使用fread和fwrite完成两个文件的拷贝

关于时间的操作

Unix时间

  1. Unix 时间戳是从1970年1月1日 (UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒。
  2. Unix 时间戳(英文为 Unix epoch, Unix time, POSIX time 或 Unix timestamp)
  3. UNIX时间戳的 0 按照ISO 8601 规范为 : 1970-01-01T00:00:00Z.
  4. 一个小时表示为UNIX时间戳格式为: 3600秒;一天表示为UNIX时间戳为86400秒,闰秒不计算。
  5. 在大多数的 Unix 系统中 Unix 时间存储为 32 位这样会引发 2038 年问题或 Y2038。
时间
1分 60
1 小时 3600
1天 86400
1周 604800
1 月(30.44 天) 2629743
1年(365.24 天) 31556736
头文件:
 #include 
函数原型:time t time(time t *tloc);
功能:获取当前的系统的unix时间的毫秒数
参数:如果是NULL,则通过返回值返回毫秒数,如果参数不是NULL,则可以通过参数得到毫秒数
返回值:成功返回毫秒数,失败返回time t类型的-1,并置位错误码
================================================================================
struct tm *localtime(const time_t *timep);
功能:通过给定的毫秒数,转变成时间
参数:毫秒数
返回值: struct tm结构体指针,失败返回NULL,并置位错误码
================================================================================
时间结构体:
struct tm原型:
struct tm 
{
	int tm sec;/* Seconds (8-68) */
	int tm min;/* Minutes (0-59) */
	int tm hour;/* Hours (@-23) */
	int tm mday;/* Day of the month (1-31) */
	int tm mon;/* Month (@-11) */
	int tm year;/* Year - 1908 */
	int tm wday;/* Day of the week (8-6, Sunday = @) */
	int tm yday;/* Day in the year (8-365, 1 Jan = 0) */
	int tm isdst; /* Daylight saving time */
};
==============================================================================
#include 
time_t sys_t = time(NULL);
struct tm *fomattime = localtime(&sys_t);
printf("%4d-%2d-%2d %2d:%2d:%2d\r",fomattime->tm_year+1900,fomattime->tm_mon+1,fomattime->tm_mday,fomattime->tm_hour,fomattime->tm_min,fomattime->tm_sec);//打印时间
输出>>
2023- 5-25 11:10:33

一、格式化控制相关的函数

1. sprintf函数

头文件:
#include 
函数原型:int sprintf(char *str, const char *format,...);
功能:向给定的字符数组中,存放进行了格式化后的字符串
参数1:字符数组首地址
参数2:格式串
参数3:格式串对应的可变参数
返回值:成功返回格式串的长度,失败返回
================================================================
char str1_buff[255] = {0};
time_t sys_t = time(NULL);
struct tm *fomattime = localtime(&sys_t);

/*将格式化的字符串存入str1_buff内*/
sprintf(str1_buff,"%4d-%2d-%2d %2d:%2d:%2d\r",fomattime->tm_year+1900,fomattime->tm_mon+1,fomattime->tm_mday,fomattime->tm_hour,fomattime->tm_min,fomattime->tm_sec);//
printf("%s\r\n",str1_buff);
输出>>
2023- 5-25 10:10:54

输入注意事项

如果要输入的格式化的字符串超过了数组的长度,则会发送数组越界的问题
编译时会给出voerflow的警告,运行时会报段错误,保险起见,我们可以使用snprintf

2. snprintf函数

函数原型:int snprintf(char *str, size t size, const char *format,...);
功能:将格式串转成字符串,但是有长度size控制,并在后面自动补上'\0'
参数1:存放格式化串的数组
参数2:格式化的长度
参数3:格式控制串
参数4:可变参数
返回值:成功返回格式化的字符格式,失败返回负数
========================================================================
char str1_buff[255] = {0};
time_t sys_t = time(NULL);
struct tm *fomattime = localtime(&sys_t);

/*将格式化的字符串存入str1_buff内,并使用sizeof(str1_buff)控制长度,防止数组越界*/
snprintf(str1_buff,sizeof(str1_buff),"%4d-%2d-%2d %2d:%2d:%2d\r",fomattime->tm_year+1900,fomattime->tm_mon+1,fomattime->tm_mday,fomattime->tm_hour,fomattime->tm_min,fomattime->tm_sec);//
printf("%s\r\n",str1_buff);
输出>>
2023- 5-25 10:10:54

3. fprintf函数

函数原型:int fprintf(FILE *stream, const char *format,...);
功能:向指定文件写入一个字符串
参数1:文件指针
参数2:格式化的字符串
参数3:可变参数
返回值:成功返回格式化的字符格式,失败返回负数
========================================================================
FILE* fp1 = NULL;
if((fp1=fopen("./file01.txt","w")) == NULL)
{//打开文件
   perror("open file");
   return -1;
}
time_t sys_t = time(NULL);
struct tm *fomattime = localtime(&sys_t);

/*将格式化的字符串输入到文件*/
fprintf(fp1,"%.4d-%.2d-%.2d %.2d:%.2d:%.2d\r",fomattime->tm_year+1900,fomattime->tm_mon+1,fomattime->tm_mday,fomattime->tm_hour,fomattime->tm_min,fomattime->tm_sec);//
fclose(fp1);
return 0;

4. fscanf函数

函数原型:int fscanf(FILE *stream, const char *format,...);
功能:从给定文件中以格式化控制符摘取数据放入到程序中
参数1:文件指针
参数2:格式化的字符串
参数3:可变参数
返回值:成功返回格式化的字符格式,失败返回负数
========================================================================
char str1_buff[255] = {0};
char str2_buff[255] = {0};
FILE* fp1 = NULL;
if((fp1=fopen("./file01.txt","r+")) == NULL)
{//打开文件读取数据
    perror("open file");
    return -1;
}
time_t sys_t = time(NULL);
struct tm *fomattime = localtime(&sys_t);
fprintf(fp1,"zh: 0x64639f16\r\nmm: 1684250390\r\n");//向文件内输入数据
fscanf(fp1,"%s%s",str1_buff,str2_buff);
printf("%s\r\n",str1_buff);
// printf("%s\r\n",str2_buff);
flose(fp1);
输出>>
zh:0x64639f16

二、fread、fwrite函数的使用

1. fread

函数原型:size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从给定文件中,读取nmemb项数据,每项数据大小为size,将数据放入ptr中
参数1:存放数据的指针,是一个万能指针,可以接收任意类型数据
参数2:读取数据每一项的大小
参数3:读取的项数
参数4:文件指针
返回值:成功返回读取的项数,当size为1时,就是成功读取的字节数,失败返回小于项数的值或者0
	  注意: 该函数不能区分是读取失败还是读取到文件结尾,需要使用ferror和feof来区分
========================================================================
FILE* fp1 = NULL;
// FILE* fp2 = NULL;
if((fp1=fopen("./file01.txt","r")) == NULL)
{//打开文件读取数据
    perror("open file");
    return -1;
}

int num = 250;
/*将数据读出文件中*/
fread(&num, sizeof(int), 1, fp1);

printf("%d\r\n", num);
fclose(fp1);

2. fwrite

函数原型:size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
功能:将ptr指向的数据,每项数据的大小为size,一共有nmemb项,写入到stream文件中
参数1:存放数据的指针,是一个万能指针,可以接收任意类型数据
参数2:读取数据每一项的大小
参数3:读取的项数
参数4:文件指针
返回值:成功返回格式化的字符格式,失败返回负数
========================================================================
FILE* fp1 = NULL;
// FILE* fp2 = NULL;
if((fp1=fopen("./file01.txt","w")) == NULL)
{//打开文件读取数据
    perror("open file");
    return -1;
}

int num = 250;
/*将数据写入文件中*/
fwrite(&num, sizeof(int), 1, fp1);

可以看到存入的是一个不能识别的二进制数据
Linux 学习记录21(IO篇)_第1张图片

3. 结构体的读写

(1. 写

typedef struct 
{
    char name[20];
    int age;
    double score;
}Stu;

int main(int argc, char const *argv[])
{
    Stu data[2] = {{"张三",18,99.9},{"李四",15,88.8}};   
    FILE* fp1 = NULL;
    // FILE* fp2 = NULL;
    if((fp1=fopen("./file01.txt","w")) == NULL)
    {//打开文件读取数据
        perror("open file");
        return -1;
    }

    /*将两个数据都写入文件中*/
    fwrite(data, sizeof(Stu), 2, fp1);

    fclose(fp1);
    return 0;
}

(2. 读

int main(int argc, char const *argv[])
{
    Stu data[2];   
    FILE* fp1 = NULL;
    // FILE* fp2 = NULL;
    if((fp1=fopen("./file01.txt","r")) == NULL)
    {//打开文件读取数据
        perror("open file");
        return -1;
    }

    /*将两个数据都写入文件中*/
    fread(data, sizeof(Stu), 2, fp1);
    printf("%s %d %.2f\r\n",data[0].name,data[0].age,data[0].score);
    printf("%s %d %.2f\r\n",data[1].name,data[1].age,data[1].score);
    fclose(fp1);
    return 0;
}

三、feof、ferror的使用

1. feof

函数原型:int feof(FILE *stream);
功能:用于判断文件是否已经到达文件末尾
参数:文件指针
返回值:如果函数返回非0值,则表示文件已到达文件末尾;否则返回0,文件还没有到达文件末尾
=================================================================================

2. ferror

函数原型:int ferror(FILE *stream);
功能:用于判断文件操作是否发生错误
参数:文件指针
返回值:函数返回非0值,则表示文件操作发生了错误;否则返回0,文件操作没有发生错误
=================================================================================

示例:

#include "public.h"

int main(int argc, char const *argv[])
{ 
    char str[10];
    FILE* fp1 = NULL;
    if((fp1=fopen("./file01.txt","r")) == NULL)
    {//打开文件读取数据
        perror("open file");
        return -1;
    }
    while(1)
    {
        fread(str,1,sizeof(str),fp1);
        printf("%s\n",str);
        if(feof(fp1))
        {
            printf("文件读取结束\r\n");
            break;
        }else if(ferror(fp1))
        {
            printf("文件读取失败\r\n");
            break;
        }
    }
    return 0;
}

思维导图

Linux 学习记录21(IO篇)_第2张图片

练习

1. 获取系统时间,并将系统时间写入文件中,实现现象

#include 
#include 
#include 
#include 
#include 
#include 
int main(int argc, char const *argv[])
{ 
    char str1[50]={0};
    char str2[50]={0};
    int cnt=0;
    int buff=0;
    FILE* fp1 = NULL;
    //FILE* fp2 = NULL;
    if((fp1=fopen("./file01.txt","r")) == NULL)
    {//打开文件写数据
        perror("open file");
        return -1;
    }

    while(!feof(fp1))
    {
        fscanf(fp1, "%d: ", &buff);
        while(str1[0] == '\n')
        {
            fscanf(fp1, "%c",&str1[0]);
        }
        str1[0]=0;
    }
    fclose(fp1);

    if((fp1=fopen("./file01.txt","a")) == NULL)
    {//打开文件写数据
        perror("open file");
        return -1;
    }

    while (1)
    {
        time_t sys_t = time(NULL);
        struct tm *fomattime = localtime(&sys_t);
        /*将格式化的字符串输入到文件*/
        sprintf(str1,"%d: %.4d-%.2d-%.2d %.2d:%.2d:%.2d\r\n",buff+cnt,fomattime->tm_year+1900,fomattime->tm_mon+1,fomattime->tm_mday,fomattime->tm_hour,fomattime->tm_min,fomattime->tm_sec);//
        if(strcmp(str1,str2) != 0)
        {
            fprintf(fp1,"%s",str1);
            printf("%s\r\n",str1);
            strcpy(str2,str1);
            cnt++;
            if(cnt == 10) break;
        }
    }

    printf("写入完成\r\n");
    fclose(fp1);
    return 0;
}

终端结果:
Linux 学习记录21(IO篇)_第3张图片

文件:
Linux 学习记录21(IO篇)_第4张图片

2. 使用fread和fwrite完成两个文件的拷贝

#include 
#include 
#include 
#include 
#include 
#include 
int main(int argc, char const *argv[])
{ 
    char str[10]={0};
    int cnt=1;
    FILE* fp1 = NULL;
    FILE* fp2 = NULL;
    if((fp1=fopen("./file01.txt","r")) == NULL)
    {//打开文件读数据
        perror("open file");
        return -1;
    }
    if((fp2=fopen("./file02.txt","w")) == NULL)
    {//打开文件写数据
        perror("open file");
        return -1;
    }
    
    while(!feof(fp1))
    {
        if(fread(str,sizeof(char),sizeof(str),fp1)==sizeof(str))
        fwrite(str,sizeof(char),sizeof(str),fp2);
    }

    printf("拷贝完成\r\n");
    fclose(fp1);
    fclose(fp2);
    return 0;
}

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

文件结果:

file1:
Linux 学习记录21(IO篇)_第5张图片
file2
Linux 学习记录21(IO篇)_第6张图片

你可能感兴趣的:(Linux学习记录,linux,学习,unix)