目录
一、fopen/fclose
二、fgetc/getc/getchar
三、fputc/putc/putchar
四、fgets/gets
五、fputs/puts
六、fread/fwrite
六、open/close
七、ftell/fssek/rewind/fflush
八、sprintf/sscanf/fprintf/fscanf
九、opendir/closedir/readdir
十、stat
十一、动态/静态库
一、fopen/fclose
其中w和w+都会清空文件,且如果文件不存在会创建新的文件
而r和r+只有在文件存在的时候才能使用,只是一个是只读,一个可以读写,也好记,你都需要读取了,文件肯定必须存在。
而a和a+就比较高级,他们和w的区别就是不会截断,就是他不会清空原本的文件,且也会和w一样创建新文件,其中a只可以写,而a+为读写。
fp = fopen("test0.txt", "w");
- 以写入模式打开文件。如果文件已经存在,其内容将被截断。如果文件不存在,则创建一个新文件。-
fp = fopen("test0.txt", "w+");
- 以读取和写入模式打开文件。如果文件已经存在,其内容将被截断。如果文件不存在,则创建一个新文件。 -
fp = fopen("test0.txt", "r");
- 以读取模式打开文件。文件必须存在;否则,将返回NULL
。 -
fp = fopen("test0.txt", "r+");
- 以读取和写入模式打开文件。文件必须存在;否则,将返回NULL
。 -
fp = fopen("test0.txt", "a");
- 以在文件末尾写入模式打开文件。如果文件不存在,则创建一个新文件。 -
fp = fopen("test0.txt", "a+");
- 以在文件末尾读取和写入模式打开文件。如果文件不存在,则创建一个新文件。
示例代码:
#include<string.h>
#include<errno.h>
#include<stdlib.h>
#include<stdio.h>
int main(int argc,const char* argv[])
{
FILE* fp;
if(fp == NULL)
{
printf("%s\n",strerror(errno));
exit(-1);
}
// fp = fopen("test0.txt","w");//只写
// fp = fopen("test0.txt","w+");
fp = fopen("test0.txt","r");
// fp = fopen("test0.txt","r+");
// fp = fopen("test0.txt","a");
// fp = fopen("test0.txt","a+");
fclose(fp);
return 0;
}
当我以只读方式打开时,本来存在test0.txt文件,程序运行不会报错,但是当我删除该文件后,报错,如下所示:
二、fgetc/getc/getchar
int fgetc(FILE *stream);
int getc(FILE *stream); //宏
int getchar(void);
成功时返回读取的字符;若到文件末尾或出错时返回EOF(-1),
getchar()等同于fgetc(stdin)
getc和fgetc区别是一个是宏一个是函数
注意事项:
1函数返回值是int类型不是char类型,主要是为了扩展返回值的范围。
2 stdin也是FILE *的指针,是系统定义好的,指向的是标准输入(键盘输入)
3 打开文件后读取,是从文件开头开始读。读完一个后读写指针会后移。读写注意文件位置!
4 调用getchar会阻塞,等待你的键盘输入
示例一: 每次只能获取一个字符
#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<stdlib.h>
int main()
{
FILE* fp;
fp = fopen("test2.txt","a+");
if(fp == NULL)
{
printf("%s\n",strerror(errno));
exit(-1);
}
int ret = fgetc(fp);
if(ret == EOF)
{
perror("fgetc");
fclose(fp);
fp = NULL;
exit(-1);
}
printf("%c\n",ret);
fclose(fp);
fp = NULL;
return 0;
}
三、fputc/putc/putchar
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
成功时返回写入的字符;出错时返回EOF
putchar(c)等同于fputc(c, stdout)
注意事项:
1返回和输入参数都是int类型
2遇到这种错误:Bad file descriptor, 很可能是文件打开的模式错误(只读模式去写,只写模式去读)
示例代码: 打印26个大写字母到1.txt文本
运行结果为:ABCDEFGHIJKLMNOPQRSTUVWXYZ,其对应的ASCII码值为65-90。
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ vi fputc.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ gcc -o fputc fputc.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ./fputc
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ls
1.txt fetc fgetc fgetc.c fopen fopen.c fputc fputc.c test01 test02 test2.txt
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ cat 1.txt
ABCDEFGHIJKLMNOPQRSTUVWXYZzhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$
详细实现代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
int main()
{
int ret = 0;
FILE* fp;
fp = fopen("1.txt","w");
if(fp == NULL)
{
printf("%s\n",strerror(errno));
exit(-1);
}
for(int ch = 65; ch <= 90; ch++ )
{
ret = fputc(ch, fp);
if(ret == EOF)
{
perror("fputc");
fclose(fp);
exit(-1);
}
}
fclose(fp);
fp = NULL;
return 0;
}
注意fputc函数的第一个参数,是要被写入的字符,但是是以该字符对应的int值进行传递的,所以需要注意ascii表,不是所有都拥有ASCII码的。
四、fgets/gets
char *gets(char *s); 读取标准输入到缓冲区s
char *fgets(char *s, int size, FILE *stream);
成功时返回s,到文件末尾或出错时返回NULL
遇到’\n’或已输入size-1个字符时返回,总是包含’\0’
注意事项:
1 gets函数已经被淘汰,因为会导致缓冲区溢出
2 fgets 函数第二个参数,输入的数据超出size,size-1个字符会保存到缓冲区,最后添加’\0’,如果输入数据少于size-1 后面会添加换行符。
打印1.txt里的所有字符:到文件末尾或出错时返回NULL
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ vim testtest.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ gcc -o test testtest.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ./test
1705568744
sadjakjfklsajf;lskaf;
sfhjkshfoihwe joijwe;f
fhnsjhfoiu ewhj flkmwe
fhjwenfoiewjfo
hfbuqwhueifohnwe
fjijewoifmwe'
sngfiuewngioejwoifjweiojfwef'fasgfewag
sahfhewqgjoie4jgewkjgoiewqngiengoijqwekgjioweqhgskdjfiwef
sahguweiqhfuiwhenfuwenuiwehfjwenf
gfuewhfiuwehfuhweuiqwheuwqheuiqwehuwqiehwqueihweuqihwuqiehqwuihqweuhqwiuhewquiw
shfshf
fhjas
d
fhuiwehfiuhoiw
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ cat testtest.c
#include<stdio.h>
int main()
{
FILE* fp;
fp = fopen("1.txt","a+");
char buf[100] = {0};
while(fgets(buf,sizeof(buf)-1,fp) != NULL)
{
printf("%s",buf);
}
fclose(fp);
return 0;
}
zhi
打印文件里有几行:
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ vim testtest.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ gcc -o test testtest.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ./test
1
1705568744
2
sadjakjfklsajf;lskaf;
3
sfhjkshfoihwe joijwe;f
4
fhnsjhfoiu ewhj flkmwe
5
fhjwenfoiewjfo
6
hfbuqwhueifohnwe
7
fjijewoifmwe'
8
sngfiuewngioejwoifjweiojfwef'fasgfewag
9
sahfhewqgjoie4jgewkjgoiewqngiengoijqwekgjioweqhgskdjfiwef
10
sahguweiqhfuiwhenfuwenuiwehfjwenf
11
gfuewhfiuwehfuhweuiqwheuwqheuiqwehuwqiehwqueihweuqihwuqiehqwuihqweuhqwiuhewquiw
12
shfshf
13
fhjas
14
d
15
fhuiwehfiuhoiw
示例代码:
成功时返回s,到文件末尾或出错时返回NULL
遇到’\n’或已输入size-1个字符时返回,总是包含’\0’
#include<stdio.h>
#include<string.h>
int main()
{
FILE* fp;
fp = fopen("1.txt","a+");
char buf[1000];
static int linecount = 0;
while(fgets(buf,sizeof(buf)-1,fp) != NULL)
{
if(buf[strlen(buf)-1] == '\n')
{ //注意判断是否是一行结束
linecount++;
printf("%d\n",linecount);
printf("%s\n",buf);
}
}
fclose(fp);
return 0;
}
新建一个名为test.txt的文本文件,向文件内输入"This is test.\n"(""内是输入的内容)
运行结果:
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ gcc -o fgets fgets.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ./fgets
This is test.\n
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ cat test.txt
This is test.\n
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$
示例代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *file = fopen("test.txt", "r+");
if (file == NULL)
{
perror("Error opening file");
exit(-1);
}
char buffer[100];
while (fgets(buffer, sizeof(buffer)-1, file) != NULL)
{
printf("%s", buffer);
}
fclose(file);
file = NULL;
return 0;
}
五、fputs/puts
int puts(const char *s);
int fputs(const char *s, FILE *stream);
成功时返回非负整数;出错时返回EOF
puts将缓冲区s中的字符串输出到stdout,并追加’\n’
fputs将缓冲区s中的字符串输出到stream,不追加 ‘\n’
运行结果:
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ cp fgets.c fputs.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ls
1.txt fetc fgetc fgetc.c fgets fgets.c fopen fopen.c fputc fputc.c fputs.c test01 test02 test2.txt test.c test.txt
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ vim fputs.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ls
1.txt fetc fgetc fgetc.c fgets fgets.c fopen fopen.c fputc fputc.c fputs.c test01 test02 test2.txt test.c test.txt
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ gcc -o fputs fputs.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ./fputs
This is test.\n
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ cat test.txt
This is test.\n
hello,worldzhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
int main()
{
FILE *file = fopen("test.txt", "r+");
if (file == NULL)
{
perror("Error opening file");
exit(-1);
}
char buffer[100];
while (fgets(buffer, sizeof(buffer)-1, file) != NULL)
{
printf("%s", buffer);
}
int ret = 0;
char array[100] = "hello,world";
ret = fputs(array,file);
if(ret == EOF)
{
perror("fputs");
fclose(file);
file = NULL;
exit(-1);
}
fclose(file);
file = NULL;
return 0;
}
六、fread/fwrite
文本文件和二进制的区别:
存储的格式不同:文本文件只能存储文本。
计算机内码概念:文本符号在计算机内部的编码(计算机内部只能存储数字0101001....,所以所有符号都要编码)
二进制读写函数格式:
size_t fread(void *ptr, size_t size, size_t n, FILE *fp);
void *ptr 读取内容放的位置指针
size_t size 读取的块大小
size_t n 读取的个数
FILE *fp 读取的文件指针
size_t fwrite(const void *ptr, size_t size, size_t n, FILE *fp);
void *ptr 写文件的内容的位置指针
size_t size 写的块大小
size_t n 写的个数
FILE *fp 要写的文件指针
注意事项:
文件写完后,文件指针指向文件末尾,如果这时候读,读不出来内容。
解决办法:移动指针到文件头;关闭文件,重新打开
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ vim fread.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ gcc -o fread fread.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ cat 2.txt
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ./fread
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ cat 2.txt
hello,worldzhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ vim fread.c
可以看到这样的话,打印不出任何东西。
#include<string.h>
#include<errno.h>
#include<stdlib.h>
#include<stdio.h>
int main(int argc,const char* argv[])
{
FILE* fp;
if(fp == NULL)
{
printf("%s\n",strerror(errno));
exit(-1);
}
// fp = fopen("test0.txt","w");//只写
fp = fopen("2.txt","w+");
// fp = fopen("2.txt","r");
// fp = fopen("test0.txt","r+");
// fp = fopen("test0.txt","a");
// fp = fopen("test0.txt","a+");
char array[100] = "hello,world";
size_t result = fwrite(array,strlen(array),1,fp);
if (ferror(fp))
{
perror("Error write");
fclose(fp);
exit(-1);
}
char buffer[100];
size_t ret = fread(buffer,10,1,fp);
if (ferror(fp))
{
perror("fread");
fclose(fp);
exit(-1);
}
printf("%s\n",buffer);
fclose(fp);
return 0;
}
修改如下:fseek(fp,0,SEEK_SET);
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ vim fread.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ gcc -o fread fread.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ./fread
hello,worl
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ cat fread.c
#include<string.h>
#include<errno.h>
#include<stdlib.h>
#include<stdio.h>
int main(int argc,const char* argv[])
{
FILE* fp;
if(fp == NULL)
{
printf("%s\n",strerror(errno));
exit(-1);
}
// fp = fopen("test0.txt","w");//只写
fp = fopen("2.txt","w+");
// fp = fopen("2.txt","r");
// fp = fopen("test0.txt","r+");
// fp = fopen("test0.txt","a");
// fp = fopen("test0.txt","a+");
char array[100] = "hello,world";
size_t result = fwrite(array,strlen(array),1,fp);
if (ferror(fp))
{
perror("Error write");
fclose(fp);
exit(-1);
}
fseek(fp,0,SEEK_SET);
char buffer[100];
size_t ret = fread(buffer,10,1,fp);
if (ferror(fp))
{
perror("fread");
fclose(fp);
exit(-1);
}
printf("%s\n",buffer);
fclose(fp);
return 0;
}
也可以采用先关闭再打开文件的方式,但是需要注意文件打开方式:我这里为了省事直接用的a+
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ vim fread.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ gcc -o fread fread.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ./fread
hello,worl
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ cat 2.txt
hello,worldzhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$
#include<string.h>
#include<errno.h>
#include<stdlib.h>
#include<stdio.h>
int main(int argc,const char* argv[])
{
FILE* fp;
if(fp == NULL)
{
printf("%s\n",strerror(errno));
exit(-1);
}
// fp = fopen("test0.txt","w");//只写
// fp = fopen("2.txt","w+");
// fp = fopen("2.txt","r");
// fp = fopen("test0.txt","r+");
fp = fopen("2.txt","a+");
// fp = fopen("test0.txt","a+");
char array[100] = "hello,world";
size_t result = fwrite(array,strlen(array),1,fp);
if (ferror(fp))
{
perror("Error write");
fclose(fp);
exit(-1);
}
fclose(fp);
fopen("2.txt","a+");
// fseek(fp,0,SEEK_SET);
char buffer[100];
size_t ret = fread(buffer,10,1,fp);
if (ferror(fp))
{
perror("fread");
fclose(fp);
exit(-1);
}
printf("%s\n",buffer);
fclose(fp);
return 0;
}
六、open/close
int close(int fd);
文件IO 打开
open
int open(const char *pathname, int flags); 不创建文件
int open(const char *pathname, int flags, mode_t mode); 创建文件,不能创建设备文件
成功时返回文件描述符;出错时返回EOF
文件IO和标准的模式对应关系:
r O_RDONLY
r+ O_RDWR
w O_WRONLY | O_CREAT | O_TRUNC, 0664
w+ O_RDWR | O_CREAT | O_TRUNC, 0664
a O_WRONLY | O_CREAT | O_APPEND, 0664
a+ O_RDWR | O_CREAT | O_APPEND, 0664
umask概念:
umask 用来设定文件或目录的初始权限
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ umask
0002
文件的关闭
int close(int fd)
关闭后文件描述符不能代表文件
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ cat 1.txt
ABCDEFGHIJKLMNOPQRSTUVWXYZhello
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ rm -rf 1.txt
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ./open
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ls
1.txt fgetc fgets.c fputc fputs.c open test02 test.c
2.txt fgetc.c fopen fputc.c fread open.c test0.txt test.txt
fetc fgets fopen.c fputs fread.c test01 test2.txt
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ cat 1.txt
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
int main()
{
int fd = open("1.txt",O_RDWR|O_CREAT|O_APPEND,0666);
if(fd == EOF)
{
perror("open");
exit(-1);
}
close(fd);
return 0;
}
七、ftell/fssek/rewind/fflush
fflush() 函数:
作用: 用于刷新流的缓冲区。当你写入或读取文件时,数据通常存储在缓冲区中,而不是立即写入或读取文件。fflush() 强制将缓冲区中的数据写入文件或清空输入缓冲区。
fseek() 函数:
作用: 用于定位文件流的位置。可以用它来移动文件指针到文件的指定位置,从而实现对文件的随机访问。
文件首SEEK_SET 当前位置SEEK_CUR 文件末尾SEEK_END
rewind() 函数:
作用: 用于将文件指针重新定位到文件的开头。相当于调用 fseek(stream, 0, SEEK_SET)。
fflush:
int fflush(FILE *fp);
成功时返回0;出错时返回EOF
将流缓冲区中的数据写入实际的文件
Linux下只能刷新输出缓冲区,输入缓冲区丢弃
ftell/fssek/rewind:
long ftell(FILE *stream);
long fseek(FILE *stream, long offset, int whence);
void rewind(FILE *stream);
fseek 参数whence参数:SEEK_SET/SEEK_CUR/SEEK_END
SEEK_SET 从距文件开头 offset 位移量为新的读写位置
SEEK_CUR:以目前的读写位置往后增加 offset 个位移量
SEEK_END:将读写位置指向文件尾后再增加 offset 个位移量
offset参数:偏移量,可正可负
注意事项:
1.文件的打开使用a模式 fseek无效
2.rewind(fp) 相当于 fseek(fp,0,SEEK_SET);
3.这三个函数只适用2G以下的文件
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ gcc test_new.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ./a.out
Current position: 13
position:0
Content: Hello, World!
Current position after fseek: 6
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$
第一次输出的位置是因为已经写入完成了,在文件末尾,输出13,指向!
第二次输出的位置为0,是因为使用了 rewind(file);其相当于 fseek(fp,0,SEEK_SET);
第三次输出位置为6,是因为使用了long fseek(FILE *stream, long offset, int whence);,其中offset设置为6,而whence设置为了SEEK_SET。
#include <stdio.h>
int main()
{
FILE *file;
char buffer[100];
// 打开文件//读写
file = fopen("example.txt", "w+");
if(file == NULL)
{
perror("fopen");
}
// 写入一些数据到文件
fprintf(file, "Hello, World!");
// 获取文件位置指针的当前位置
long position = ftell(file);
if(position == EOF)
{
perror("ftell");
}
printf("Current position: %ld\n", position);
// 设置文件位置指针到文件的开头
rewind(file);
position = ftell(file);
printf("position:%ld\n",position);
// 读取文件内容并打印
fgets(buffer, sizeof(buffer), file);
printf("Content: %s\n", buffer);
// 设置文件位置指针到指定位置
fseek(file, 6, SEEK_SET);
// 获取文件位置指针的当前位置
position = ftell(file);
printf("Current position after fseek: %ld\n", position);
// 关闭文件
fclose(file);
return 0;
}
八、sprintf/sscanf/fprintf/fscanf
格式化输出
int fprintf(FILE *stream, const char *fmt, …);
int sprintf(char *s, const char *fmt, …);
成功时返回输出的字符个数;出错时返回EOF
格式化输入
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);
循环打印现在的时间:
#include<stdio.h>
#include<time.h>
int main()
{
time_t ctime;
struct tm* current_time;
while(1)
{
ctime = time(NULL);
current_time = localtime(&ctime);
printf("Current time: %04d-%02d-%02d\n",
current_time->tm_year+1900,
current_time->tm_mon+1,
current_time->tm_mday);
}
return 0;
}
time()用来获取系统时间(秒数)
time_t time(time_t *seconds) 1970.1.1 0:0:0
localtime()将系统时间转换成本地时间
struct tm *localtime(const time_t *timer)
struct tm {
int tm_sec; /* 秒,范围从 0 到 59 */
int tm_min; /* 分,范围从 0 到 59 */
int tm_hour; /* 小时,范围从 0 到 23 */
int tm_mday; /* 一月中的第几天,范围从 1 到 31 */
int tm_mon; /* 月份,范围从 0 到 11 */
int tm_year; /* 自 1900 起的年数 */
int tm_wday; /* 一周中的第几天,范围从 0 到 6 */
int tm_yday; /* 一年中的第几天,范围从 0 到 365 */
int tm_isdst; /* 夏令时 */
};
注意:
int tm_mon; 获取的值要加1是正确的月份
int tm_year; 获取的值加1900是正确的年份
使用fprintf和sprintf
运行结果:
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ gcc -o fprintf fprintf1.c
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ./fprintf
1705568744
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ ls
1.txt fetc fgetc.c fopen.c fputc fread test01 test.c
2.txt fflush fgets fprintf fputc.c fread.c test02 test_new.c
a.out fflush.c fgets.c fprintf1.c fputs open test0.txt test.txt
example.txt fgetc fopen fprintf.c fputs.c open.c test2.txt
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$ cat 1.txt
1705568744
zhibin@zhibin-virtual-machine:~/code_Learning/code_2024_1_18/lesson_csdn$
示例代码:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char* argv[])
{
char buff[100] = {0};
FILE* fp;
fp = fopen("1.txt", "a+");
if (fp == NULL)
{
perror("fopen");
exit(-1);
}
time_t ctime = time(NULL);
sprintf(buff, "%ld", ctime);
printf("%ld\n", ctime);
fprintf(fp, "%ld\n", ctime);
fclose(fp);
return 0;
}
九、opendir/closedir/readdir
#include <dirent.h>
DIR *opendir(const char *name);
DIR *fdopendir(int fd); 使用文件描述符,要配合open函数使用
DIR是用来描述一个打开的目录文件的结构体类型
成功时返回目录流指针;出错时返回NULL
读取目录
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
struct dirent是用来描述目录流中一个目录项的结构体类型
包含成员char d_name[256] 参考帮助文档
成功时返回目录流dirp中下一个目录项;
出错或到末尾时时返回NULL
关闭目录
closedir函数用来关闭一个目录文件:
#include <dirent.h>
int closedir(DIR *dirp);
成功时返回0;出错时返回EOF
struct dirent {
ino_t d_ino; /* inode number 索引节点号*/
off_t d_off; /* not an offset; see NOTES 在目录文件中的偏移*/
unsigned short d_reclen; /* length of this record 文件名长*/
unsigned char d_type; /*type of file; not supported by all filesystem types 文件类型*/
char d_name[256]; /* filename 文件名,最长255字符*/
};
运行结果:
linux@linux:~/code_Linux/2024_1_15/test$ ./dir
test
..
.
lesson
linux@linux:~/code_Linux/2024_1_15/test$ ;s
bash: syntax error near unexpected token `;'
linux@linux:~/code_Linux/2024_1_15/test$ cd ..
linux@linux:~/code_Linux/2024_1_15$ ls
lesson test
linux@linux:~/code_Linux/2024_1_15$
示例代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<errno.h>
#include<unistd.h>
#include<time.h>
#include<dirent.h>
int main(int argc,const char* argv[])
{
DIR* dirp;
struct dirent* dir;
dirp = opendir("/home/linux/code_Linux/2024_1_15/");
if(dirp == NULL)
{
perror("opendir");
exit(-1);
}
while((dir = readdir(dirp)) != NULL)
{
printf("%s\n",dir->d_name);
}
closedir(dirp);
dirp = NULL;
return 0;
}
十、stat
#include <sys/stat.h>
int stat(const char *path, struct stat *buf);
int lstat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
成功时返回0;出错时返回EOF
如果path是符号链接stat获取的是目标文件的属性;而lstat获取的是链接文件的属性
struct dirent {
ino_t d_ino; /* inode number 索引节点号*/
off_t d_off; /* not an offset; see NOTES 在目录文件中的偏移*/
unsigned short d_reclen; /* length of this record 文件名长*/
unsigned char d_type; /*type of file; not supported by all filesystem types 文件类型*/
char d_name[256]; /* filename 文件名,最长255字符*/
};
S_ISREG(m) 是常规文件吗?
S_ISDIR (m) 目录吗?
S_ISCHR (m) 字符设备?
S_ISBLK (m) 块设备?
S_ISFIFO(m) FIFO(命名管道)?
S_ISLNK (m) 符号链接呢? (不是posix . 1的授权- 1996)。
S_ISSOCK (m) 套接字? (不是posix . 1的授权- 1996)。
struct stat {
mode_t st_mode; //文件对应的模式,文件,目录等
ino_t st_ino; //inode节点号
dev_t st_dev; //设备号码
dev_t st_rdev; //特殊设备号码
nlink_t st_nlink; //文件的连接数
uid_t st_uid; //文件所有者
gid_t st_gid; //文件所有者对应的组
off_t st_size; //普通文件,对应的文件字节数
time_t st_atime; //文件最后被访问的时间
time_t st_mtime; //文件内容最后被修改的时间
time_t st_ctime; //文件状态改变时间
blksize_t st_blksize; //文件内容对应的块大小
blkcnt_t st_blocks; //伟建内容对应的块数量
};
这样始终打印的都是test.c的大小。
#include<stdio.h>
#include<stdlib.h>
#include<dirent.h>
#include<time.h>
#include<sys/stat.h>
int main()
{
DIR* dirp;
dirp = opendir("/home/linux/code_Linux/");
if(dirp == NULL)
{
perror("open");
exit(-1);
}
struct dirent* dir;
struct stat* buf;
while((dir = readdir(dirp)) != NULL)
{
//遍历所有文件
printf("%s:",dir->d_name);
//打印大小
stat("test.c",buf);
printf(" %02d",(int)buf->st_size);
printf("\n");
}
closedir(dirp);
dirp = NULL;
return 0;
}
遍历一个文件夹下所有文件,并打印文件大小和日期:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>
#include<dirent.h>
#include<time.h>
#include<sys/stat.h>
int main(int argc,const char* argv[])
{
DIR* dir;
dir = opendir("/home/zhibin/code_Learning/code_2024_1_17/lesson03");
if(dir == NULL)
{
//打开失败
perror("opendir");
exit(-1);
}
//打开lesson03下的目录
//遍历目录下的条目
//使用readdir函数
struct dirent* readret;
struct stat buf;
int ret = 0;
while(NULL != (readret = readdir(dir)))
{
printf("%s:",readret->d_name);
//打印时间和大小
char file_path[256];
snprintf(file_path, sizeof(file_path), "%s/%s",
"/home/zhibin/code_Learning/code_2024_1_17/lesson03", readret->d_name);
//拼接出正确路径
ret = stat(file_path,&buf);
if(ret == EOF)
{
perror("stat");
closedir(dir);
exit(-1);
}
printf(" %d", (int)buf.st_size);
struct tm* last;
last = localtime(&buf.st_ctime);
printf(" %d-%d-%d %d:%d", last->tm_year + 1900,
last->tm_mon + 1, last->tm_mday, last->tm_hour, last->tm_min);
printf("\n");
}
return 0;
}
十一、动态/静态库
静态库
创建静态库步骤:
1 . 编写库文件代码,编译为.o 目标文件。
2. ar 命令 创建 libxxxx.a 文件
ar -rsv libxxxx.a xxxx.o
注意:1 静态库名字要以lib开头,后缀名为.a
2 没有main函数的.c 文件不能生成可执行文件。
链接错误:
test.c:(.text+0x15):对‘hello’未定义的引用
collect2: error: ld returned 1 exit status
含义:表示hello函数在编译的源码内没有找到实现
解决:实现代码或者找到对应函数的库并且链接它。
链接静态库:
gcc -o 目标文件 源码.c -L路径 -lxxxx
-L 表示库所在的路径
-l 后面跟库的名称
动态库的生成步骤:
1. 生成位置无关代码的目标文件
gcc -c -fPIC xxx.c xxxx.c ....
2. 生成动态库
gcc -shared -o libxxxx.so xxx.o xxx.o ....
3. 编译可执行文件
gcc -o 目标文件 源码.c -L路径 -lxxxx
执行动态库的可执行文件错误
./test: error while loading shared libraries: libmyheby.so: cannot open shared object file: No such file or directory
含义:可执行文件所使用的动态库找不到
解决办法:
找到动态库,添加到/usr/lib里面
或者使用export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:你的动态库目录
添加在~/.bashrc 文件里面
使用source ~/.bashrc 生效。
查看可执行文件使用的动态库:
ldd 命令 : ldd 你的可执行文件
root@haas-virtual-machine:/mnt/hgfs/share/newIOP# ldd test
linux-vdso.so.1 => (0x00007fff6548d000)
libmyheby.so => /mnt/hgfs/share/newIOP/day5/libmyheby.so (0x00007f5c89521000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5c89144000)
/lib64/ld-linux-x86-64.so.2 (0x000055fe52211000)
root@haas-virtual-machine:/mnt/hgfs/share/newIOP/day5# ldd test
linux-vdso.so.1 => (0x00007ffcb652c000)
libmyheby.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbeeffaf000)
/lib64/ld-linux-x86-64.so.2 (0x0000561003c3b000)