读完标题,不禁会提出两个问题:1、如何进行文件的操作呢?2、如何获取系统时间呢?
下面就这两方面进行简单说明。
一、文件操作
文件操作必须遵从的过程是:打开,读写,关闭。
如下面的代码所示,执行的操作是:打开(如果不存在该文件,就创建)文件 file.txt,向文件中写入 “文件操作成功!”,然后关闭文件。
#include <stdio.h>
int main(void) {
FILE* stream;// 文件指针
errno_t err;// 错误码
char* filename = "file.txt";// 文件名
// 打开,以在文件末尾追加(append)数据的形式打开文件filename
err = fopen_s(&stream, filename, "a");
if (err == 0) {
printf("文件 %s 打开成功\n", filename);
} else {
printf("文件 %s 打开失败\n", filename);
}
// 写入数据
if (stream != NULL) {
// 向文件末尾追加一段文字。
fprintf(stream, "%s", "文件操作成功!\n");
}
// 关闭
if (stream != NULL) {
// 关闭文件指针,先要判断是否为空
err = fclose(stream);
if (err == 0) {
printf("文件 %s 关闭成功\n", filename);
} else {
printf("文件 %s 关闭失败\n", filename);
}
}
}
01、fopen_s函数
功能: 以 mode 的方式打开文件 filename ,将文件指针赋值给 *pFile。
语法如下:
errno_t fopen_s( FILE** pFile, const char *filename, const char *mode );
pFile:一个指向文件指针的指针,它将接收指向打开的文件的指针。
filename:文件名。
mode:文件打开的方式,可参考 链接。
返回值: 如果打开成功返回 0,否则返回相应的错误码。
02、fprintf函数
功能: 向文件指针 stream 指向的文件写入 format 格式的数据。
语法如下:
int fprintf( FILE *stream, const char *format [, argument ]... );
stream:文件指针。
format:格式控制字符串。
argument:可选参数。
返回值: 写入到文件的字节数,通常用不到,可忽略。
说明:
- 和 printf 函数非常相似,区别是第一个参数,是文件指针,而 printf 的文件指针是标准输出设备。
- 不止这一个函数可以写操作,还有 fwrite 函数,fputs 函数等等。
03、fclose函数
功能: 关闭文件指针 stream。
语法如下:
int fclose( FILE *stream );
stream:文件指针。
返回值: 如果文件关闭成功,则返回 0,否则返回 EOF。
通过上述文件操作的代码和说明,我们已经学会了如何向txt文件写入一个字符串。
那么现在要考虑的问题是 如何获取时间 并将时间转为字符串。
二、获取时间
获取时间的过程是:先获取系统时间,然后转换成本地时间。最后将时间转成字符串(方便写入文件中)。
下面代码的功能是获取当前时间并输出到标准输出设备。
代码示例:
#include <stdio.h>
#include <time.h>
int main(void) {
char timebuf[21];// 字符串形式保存时间
time_t ltime;// 时间戳
struct tm today;// 本地时间结构体
errno_t err;// 错误码
time(<ime);// 获取系统时间
err = _localtime64_s(&today, <ime);// 转换为本地时间
if (err != 0) {
printf("无法转换为本地时间\n");
exit(1);
}
// 将时间转换为字符串,自定义格式
strftime(timebuf, 21, "%Y/%m/%d %T%n", &today);
printf(timebuf);
}
执行结果示例:
2019/10/16 22:46:20
01、time函数
功能: 获取系统时间保存到 time_t 型变量中。
语法如下:
time_t time( time_t *destTime ); // 获取系统时间,参数是指向时间的存储位置的指针
destTime:指向时间戳的指针。
返回值: 从 1970/01/01 00:00:00
以来经过的秒数。有错误返回 -1。
02、_localtime64_s函数
功能: 将时间戳转换成本地时间的结构体。后者更容易使用。
语法如下:
errno_t _localtime64_s(
struct tm* tmDest, // 指向要填充的时间结构体
__time64_t const* sourceTime // 指向时间的存储位置的指针
); // 将时间转换为本地时间结构体
tmDest:本地时间结构体指针。
sourceTime:指向时间的存储位置的指针。
返回值: 转换成功返回 0,否则返回对应的错误码。
03、strftime函数
功能: 按照 format 指定的格式将 timeptr 指向的结构体内的数据依次填充到字符串 strDest 中。
语法如下:
size_t strftime(
char *strDest, // 保存时间的字符串
size_t maxsize, // strDest指向的大小
const char *format, // 格式控制串,参照使用手册。
const struct tm *timeptr // 时间结构体
);
strDest:保存时间的字符串指针。
maxsize:strDest指向的大小。
format:格式控制字符串。
timeptr:本地时间结构体。
返回值: 返回填充的字节数,如果超过了 maxsize,返回 0。
到这里差不多就已经掌握了简单的写入时间操作。可以试试自己写一写。
不会也没关系,下面的代码是封装好的。复制到项目中就可以直接调用。
三、完整代码
先来看一下函数原型,这四个函数可以调用。
01、函数原型
// 功能:向txt文件filename末尾追加格式为YYYY/MM/DD HH:MM:SS的时间
// filename是文件名,文件名本身不带双引号
void log_time_filename(char const* filename);
// 功能:向stream指向的文件末尾追加格式为YYYY/MM/DD HH:MM:SS的时间
// stream必须打开
void log_time_stream(FILE* stream); // 参数是文件指针
// 功能:向txt文件filename末尾追加格式为YYYY/MM/DD HH:MM:SS的时间并换行
// filename是文件名,文件名本身不带双引号
void log_time_line_filename(char const* filename);
// 功能:向stream指向的文件末尾追加格式为YYYY/MM/DD HH:MM:SS的时间并换行
// stream必须打开
void log_time_line_stream(FILE* stream);
02、log.h
文件
将代码保存到与 调用文件 在同一级目录下的 log.h 文件中。有四个外部函数可供调用。
/*********************************************************************
文件: log.h
环境: Windows 10
IDE: Visual Studio 2019
版本: 1.5.0.1910
功能: 1、向 <文件名.txt> 文件末尾追加当前系统时间
2、向 <FILE* stream> 指向的文件末尾追加当前系统时间
备注: 1、目前只有默认日期格式,即YYYY/MM/DD hh:mm:ss
2、支持换行和不换行两种形式
日期: 2019年10月16日15:42:15
作者: wowpH
*********************************************************************/
#pragma once
#pragma message("log.h - wowpH - 1.5.0.1910")
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// 时间格式的最大长度
#define MAX_TIME_MODE_SIZE 21
//
// 可调用的函数
//
// 通过文件名追加时间
void log_time_filename(char const* filename);
// 通过文件指针追加时间
void log_time_stream(FILE* stream);
// 通过文件名追加时间,换行
void log_time_line_filename(char const* filename);
// 通过文件指针追加时间,换行
void log_time_line_stream(FILE* stream);
//
// 供内部使用的函数,外部调用可能出错
//
// 向strDest写入当前时间
void get_local_time(char* strDest);
// 打开文件
void open_file(FILE** stream, char const* filename);
// 关闭文件
void close_file(FILE* stream);
03、log.c
文件
将代码保存到与 调用文件 同一级目录下的 log.c 文件中。
#include "log.h"
const char* null_stream = "文件指针为空,请先打开一个文件!";
const char* error_open = "文件打开失败!";
const char* error_close = "文件关闭失败!";
const char* error_to_localtime = "无法转换为本地时间!";
void log_time_filename(char const* filename) {
FILE* stream = NULL;
open_file(&stream, filename);
log_time_stream(stream);
close_file(stream);
}
void log_time_stream(FILE* const stream) {
if (stream != NULL) {
char time[MAX_TIME_MODE_SIZE];
get_local_time(time);
fprintf(stream, "%s", time);
} else {
printf("%s\n", null_stream);
exit(-1);
}
}
void log_time_line_filename(char const* filename) {
FILE* stream = NULL;
open_file(&stream, filename);
log_time_line_stream(stream);
close_file(stream);
}
void log_time_line_stream(FILE* stream) {
log_time_stream(stream);
fprintf(stream, "\n");
}
static void get_local_time(char* strDest) {
time_t ltime;
time(<ime);
struct tm today;
errno_t err;
err = _localtime64_s(&today, <ime);
if (err != 0) {
printf("%s\n", error_to_localtime);
exit(-1);
}
// 将时间转换为字符串,自定义格式
strftime(strDest, MAX_TIME_MODE_SIZE, "%Y/%m/%d %T", &today);
}
static void open_file(FILE** stream, char const* filename) {
errno_t err = 0;
err = fopen_s(stream, filename, "a");
if (err != 0) {
printf("%s\n", error_open);
exit(-1);
}
}
static void close_file(FILE* stream) {
if (stream != NULL) {
errno_t err = 0;
err = fclose(stream);
if (err != 0) {
printf("%s\n", error_close);
exit(-1);
}
}
}