C实现 每隔1s向time.txt文件输出系统时间(C I/O函数)

平台:x86/Debian Linux/gcc


1 题目

编程读写一个文件test.txt,每隔1s向文件中写入一行记录,类似于这样:

1 2009-7-30 15:16:42

2 2009-7-30 15:16:43

该程序应该是无限循环,直到按Ctrl + C终止。下次再启动程序时再test.txt文件末尾追加记录,并且序号能够持续上次的序号,比如:

1 2009-7-30 15:16:42

2 2009-7-30 15:16:43

3 2009-7-30 15:19:02

4 2009-7-30 15:19:03

5 2009-7-30 15:19:04

 

2 编程实现

(1) C代码

/* Filename:	out_date_and_time.c
 * Brife:	Output date and time to time.txt one by one second
 * Date:	2014.8.7 Thursday
 * Author:	One fish
 */
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>



//------------Maro------------------
#define EPOCH_YEAR	1900
#define EPOCH_MONTH	1
#define EPOCH_DAY	1
#define OUT_FILE	"time.txt"



//------------Function decalre-------
void get_localtime(unsigned long int file_num);
unsigned long int find_file_end(const char *file);



//----------Golbal varibles----------
FILE *fp = NULL;




int main(void)
{
	unsigned long int file_num = 0;

	file_num	= find_file_end(OUT_FILE);		
	printf("line number: %d\n", file_num);
	
	while( 1 ){
		get_localtime( file_num + 1 );
		sleep(1);
	}
	return 0;
}




/*@Brife:	Open file and find file end line number
 *@Arg:		file is the opened file
 *@Rel:		Return the file number
 */
unsigned long int find_file_end(const char *file)
{
	char buf[30];
	int file_num = 0;

	fp	= fopen(file, "a+");
	if(NULL != fp){
		
		//File is empty
		if( NULL == fgets(buf, 30, fp) )
			return 0;
		
		//Move fp to the start of the last line of the file
		fseek(fp, -strlen(buf), SEEK_END);
		fgets(buf, 30, fp);
	
		//Or line number bigger than long long int scope
		if(1 != sscanf(buf, "%d", &file_num) ){
			printf("*.txt format is not correct\n");
			return 0;
		}

		return file_num;
	}else{
		printf("Open %s failed\n", OUT_FILE);
	}
}



/*@Brife:	Get current date and output to time.txt
 * 		Should be called after find_file_end()
 *@Arg:		File_num, the line number should be printed
 */
void get_localtime(unsigned long int file_num)
{

	time_t *t = NULL;
	static unsigned long int num = 0;
	if(num <= file_num){
		num	= file_num;
	}

	t	= (time_t *)malloc(sizeof(time_t));

	if(NULL != t){
		struct tm *ptm = NULL;
		
		//Get the time as the number of seconds since the Epoch, 1970-01-01 00:00 + 0000(UTC)
		//Translate calendar time to broken-down time
		time(t);
		ptm	= localtime(t);
		
		if(NULL != fp){
			fprintf(fp, "%d %d-%d-%d\t", num, EPOCH_YEAR + ptm->tm_year, EPOCH_MONTH + ptm->tm_mon, EPOCH_MONTH + ptm->tm_mday);
			fprintf(fp, "%d:%d:%d\n", ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
			fflush(fp);
			++num;
		}else{
			printf("%s Not found\n", OUT_FILE);
		}
	}
	free(t);
}


(2) 运行结果

编译程序:gcc  -o  out_date_and_time  out_date_and_time.c

第一次运行程序一小会后按Ctrl + C终止程序,隔一小会再运行程序。time.txt文件内容如下:

1 2014-8-9    14:40:41

2 2014-8-9    14:40:42

3 2014-8-9    14:40:43

4 2014-8-9    14:40:44

5 2014-8-9    14:40:48

6 2014-8-9    14:40:49

7 2014-8-9    14:40:50

3 man page + 验证

(1) fgets()

原型:char *fgets(char *s, int size, FILE *stream)

  • 用户定义的缓冲区s的sizeof(s)要大于等于size,如果小于size则在fgets读到size-1字符给s后会继续添加一个’\0’字符。使缓冲区s的使用越界。
  • fgets读一个新建的文件返回NULL。fgets读一个用”backspace”退隔调所有内容的文件,输出fgets的返回值是一个换行。

(2) fseek()

原型:int fseek(FILE  *stream, long  offset, int  whence)

对以下两个不同文件内容:

Figure1.文件1
C实现 每隔1s向time.txt文件输出系统时间(C I/O函数)_第1张图片
Figure2.文件2

文件1只有1行数据(1 2014-8-9 15:15:55)并手动输入回车跳到文件1的第二行。文件2的每行内容是由fprintf输出的,行尾带回车。文件1和文件2每行数据长度相同为len,使fp指向文件1时,fseek(fp, -len, SEEK_END)时fp指向1后面的空格。fp指向文件2时,用fseek(fp, -len,SEEK_END)时fp指向第七行(黄色数字为行号)的数字7。


(3) time()和localtime()

用以上代码中time()和localtime()联用,由后者返回struct tm后,加上起始时间后tm_mday比实际时间多一天。


(4) fflush()

原型:fflush(FILE *stream)

因为fprintf属C标准库I/O库函数,stream指向的文件属常规文件(标准输入输出可能为行缓冲),其缓冲类型为全缓冲类型。故而在缓冲区满或程序正常结束前fprintf输出的内容全在缓冲区,在缓冲区未满时按Ctrl + C 后exit()函数没有得到运行,没有得到flush操作,故而stream指向的文件中无内容输出。所以要在每个fprintf函数后面添加ffush()函数,强制进入内核将内容输出到文件中。

[2014.8.8 -- 14.40 - 15.47]

CBNote Over.

你可能感兴趣的:(C实现 每隔1s向time.txt文件输出系统时间(C I/O函数))