基于缓冲区的文件操作:
属于高级的IO操作,其中以printf函数是基于缓冲区的文件操作,基于缓冲区的文件操作通常使用标准库中的<stdio.h>头文件提供的函数。这些函数大多数以f开头,表示它们是“文件”(file)相关的操作。
缓冲区的输出条件:
程序正常结束;printf遇到\n也可以全部输出;缓冲区存满1024字节后将输出1024字节内容;遇到 fflush(stdout);
1.基于非缓冲区文件操作
属于低级IO操作,其中有打开文件函数open、读写write、read函数、close、控制光标位置lseek函数等。
1.打开文件(open函数)
#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
以下的宏定义自由选择:
O_CREAT //如果文件不存在就创建文件, 存在, 不起作用
O_TRUNC //清空
O_APPEND //追加
O_EXCL:要求和O_CREAT连用,文件如果不存在,创建并打开,如果文件存在open直接返回失败(-1)
mode:由flags决定,如果flags里面有O_CREAT,此时需要提供mode,否则,不用提供;mode文件的权限:八进制数,最终的文件权限:你提供的mode &(~umask)
返回值:成功int类型的文件描述符,失败返回-1;
例:打开 1.txt,读写的方式打开,文件不存在创建,文件存在清空写
open(“1.txt”,O_RDWR|O_CREAT|O_TRUNC,0666);// 文件的权限被设置为 0666,这意味着文件所有者、组和其他用户都有读写权限(但注意,实际权限可能会受到umask的影响)
2.关闭文件(close)
#include <unistd.h>
int close(int fd);
形参: open的返回值
返回值:returns zero on success. On error, -1 is returned
3.写操作(write)
#include <unistd.h>
ssize_t write(int fd, const void*buf, size_t count);
参数
fd:open的返回值
buf:要写入的内容的首地址void *
count:写入的字节数
返回值:成功返回真正写入的字节数,失败返回-1
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//获取用户输入的账号和密码,并将它们写入到一个名为 "mima.txt" 的文件中。
int main()
{
char username[32]={0};
char passward[8]={0};
printf("请输入账号:\n");
scanf("%s",username);
getchar();
printf("请输入密码:\n");
scanf("%s",passward);
getchar();
int fb = open("mima.txt",O_WRONLY);
if (fb == -1) {
perror("打开文件失败open");
return 1;
}
write(fb,username,sizeof(username));
write(fb,"\n",1);
write(fb,passward,sizeof(passward));
close(fb);
return 0;
}
4.读操作(read)
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
参数
fd:open的返回值
buf:读取到的内容存放的位置,提供空间即可
count:要读取的字节数
返回值:成功返回真正读取到的字节数,失败返回-1;
5.光标偏移(lseek)
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset,int whence);
参数
fd:open的返回值
offset:偏移量
+n 往文件末尾方向偏移n字节
-n 往文件开头方向偏移n字节
whence:偏移时的参考位置
SEEK_SET //文件开头
SEEK_CUR //文件当前位置
SEEK_END //文件末尾
返回值: 执行操作之后, 光标位置距离文件开头的偏移量
可以用此函数求文件大小:off_t size = fseek(fd,0,SEEK_END);
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//读取文件中的的账号密码
int main()
{
int fb = open("mima.txt",O_RDONLY);
char name[32]={0};
char ward[8]={0};
loop:
printf("请输入账号:\n");
scanf("%s",name);
getchar();
lseek(fb,0,SEEK_SET);
int a=sizeof(name);
char *p=malloc(a);
read(fb,p,a);
if(strcmp(p,name)==0)
{
read(fb,p,1);
printf("请输入密码:\n");
scanf("%s",ward);
getchar();
a=sizeof(ward);
read(fb,p,a);
if(strcmp(p,ward)==0)
{
printf("账号和密码输入正确\n");
close(fb);
return 0;
}
else
{
printf("密码输入错误\n");
close(fb);
return -1;
}
}
else
{
printf("账号输入错误\n");
goto loop;
close(fb);
return -1;
}
return 0;
}
可以利用读写操作实现文档的复制功能:从命令行参数指定的第一个文件中读取内容,然后将这些内容写入到第二个文件中,并最后从第二个文件中读取并打印内容。
(案例仅供参考,在打开文件时,我没有检查open函数是否成功返回了文件描述符。如果文件不存在或无法打开,则open会返回-1,但我没有处理这种情况,还有read和write函数也可能失败,也没有检查它们的返回值。在写代码时注意检查函数的返回值,来判断函数是否执行成功)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc,char *argv[])
{
//检查命令行参数的数量如果参数数量不是3(包括程序名和两个文件名)则打印错误消息并结束程序
if(argc != 3)
{
printf("参数错误!\n");
}
for (int i = 0; i < argc; i++)
{
printf("argv[%d]=%s\n",i,argv[i]);
}
//使用open函数以只读模式打开第一个文件,并将返回的文件描述符存储在fd中
int fd = open(argv[1],O_RDONLY);
//将文件位置指针移动到文件的末尾,然后获取文件的大小
off_t size = lseek(fd,0,SEEK_END);
if (size==0)
{
close(fd);
printf("%s无内容\n",argv[1]);
return -1;
}
//将文件位置指针重置回文件的开头
lseek(fd,0,SEEK_SET);
//动态分配内存以存储整个文件的内容,分配的大小等于文件的大小
char *p=malloc(size);
read(fd,p,size);
printf("p:%s",p);
//以读写模式打开或创建第二个文件,并设置其权限为0666返回的文件描述符存储在fd1中
int fd1=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0666);
write(fd1,p,size);
close(fd);
close(fd1);
//以只读模式重新打开第二个文件,并将返回的文件描述符存储在fd2中
int fd2 = open(argv[2],O_RDONLY);
lseek(fd2,0,SEEK_SET);
ssize_t res=read(fd2,p,size);
printf("res=%ld\n",res);
printf("%s:%s",argv[2],p);
close(fd2);
return 0;
}
2.时间编程
1.和时间相关的指令
终端指令:data
终端输入: Cal
2.和时间编程相关的API函数
1)获取日历时间 -- 时间的秒数(time)
日历时间:1970年1月1日0点0分0秒举例现在的秒数
#include <time.h>
time_t time(time_t *tloc);
使用方法:
方式1:timt_t t = time(NULL);//time的返回值就是日历时间;
方式2:time_t t = 0;
time(&t); //t里面就存放当前的日历时间
2)获取本地时间(localtime)
#include <time.h>
struct tm *localtime(const time_t *timep);
参数
timep:日历时间,传日历时间地址
返回值: struct tm {
int tm_sec; /* 秒 */
int tm_min; /* 分 */
int tm_hour; /* 时 */
int tm_mday; /* Day of the month (1-31) */
int tm_mon; /* Month (0-11)+1 */
int tm_year; /* Year - 1900 +1900 */
int tm_wday; /* Day of the week (0-6, Sunday = 0) */
int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */
int tm_isdst; /* Daylight saving time */};
#include <stdio.h>
#include <time.h>
#include <unistd.h>
//打印本地时间60次(一分钟)
void Get_Time(void)
{
time_t sj = time(NULL);
struct tm *psj=localtime(&sj);
printf("%d-%02d-%02d %02d:%02d:%02d\n",psj->tm_year+1900,psj->tm_mon+1,psj->tm_mday,psj->tm_hour,psj->tm_min,psj->tm_sec);
}
int main()
{
int num=60;
while (num--)
{
Get_Time();
sleep(1);
}
return 0;
}
3)获取格林威治 gmtime
struct tm *gmtime(const time_t *timep);
形参和返回值和localtime一样,结果中的时间形式是美国时间
4)获取时间的字符串(ctime)
char *ctime(const time_t *timep);
形参:timep日历时间,传地址
返回值:关于时间的字符串
5)获取时间的字符串 - asctime
char *asctime(const struct tm *tm);
形参:localtime或者gmtime的返回值
返回值:关于时间的字符串
如果传参传的是localtime的返回值,关于时间的字符串是准确的
如果传参传的是gmtime的返回值,关于时间的字符串差8hour
3.关于时间的字符串
功能:我们可以根据format指向字符串中格式命令把timeptr中保存的时间信息放在strDest指向的字符串中,最多向strDest中存放maxsize个字符。该函数返回向strDest指向的字符串中放置的字符数。
函数strftime()的操作有些类似于sprintf():识别以百分号(%)开始的格式命令集合,格式化输出结果放在一个字符串中。格式化命令说明串strDest中各种日期和时间信息的确切表示方法。格式串中的其他字符原样放进串中。格式命令列在下面,它们是区分大小写的。
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
参数
s:存放格式化时间字符串
max:时间字符串最大长度
format:自定义格式,按照此格式,放在第一个参数给的字符串中
tm:时间描述的结构体(gmtime / localtime返回值)
如果是gmtime得到的结构体指针,时间差8小时
如果是localtime得到的结构体指针,时间准确
%a 星期几的简写
%A 星期几的全称
%b 月份的简写
%B 月份的全称
%c 标准的日期的时间串
%C 年份的后两位数字
%d 十进制表示的每月的第几天
%D 月/天/年
%e 在两字符域中, 十进制表示的每月的第几天
%F 年-月-日
%g 年份的后两位数字, 使用基于周的年
%G 年分, 使用基于周的年
%h 简写的月份名
%H 24 小时制的小时
%I 12 小时制的小时
%j 十进制表示的每年的第几天
%m 十进制表示的月份
%M 十时制表示的分钟数
%n 新行符
%p 本地的 AM 或 PM 的等价显示
%r 12 小时的时间
%R 显示小时和分钟: hh:mm
%S 十进制的秒数
char buf[128] = {0}
例:strftime(buf,sizeof(buf),”%D %S %R”,loctm);