Liunx系统的文件IO

一、标准IO和文件IO的区别:

    1>标准IO拥有缓冲区,文件IO没有

    2>标准IO是文件IO的基础上封装缓冲区形成

    3>标准IO是应用层IO 来自C库

            文件IO是底层IO  来自系统

       ------------文件IO在移植性上面,优于标准IO

    4>标准IO大多数来自stdio.h

            文件IO的头文件相对比较多

缓冲区的分类:

1>全缓冲:主要针对普通文件

    只有当缓冲区域满的时候,才会执行IO操作

2>行缓冲:标准输入

     当缓冲区域满或者遇到“\n”;

3>不缓冲:标准错误输出

    直接输出

二、时间编程

1>时间编程 — 智能手表 —哎哟我去
获取系统时间
1>世界标准时间:格林尼治时间
简称UTC,是一种规范世界时间的规则,将地球划分为24个时区

		2>系统标准时间
			计算方式: 1970年 1月 1日 0时0分0秒   到  此时此刻的秒数 
			1970:UNIX time的起始.世界上大多数计算机语言都是以这个时间
				 为开始的.
				 我们以前用的系统32位:可以存放236年的秒数
								 64
								 
		3>获取系统时间
			time
			#include <time.h>
			time_t time(time_t *tloc);
			功能: 
					获取到系统标准时间返回到某个地方
			
			参数: 
					用来保存秒数的变量地址 
			
			返回值: 
					成功:获取到的秒数
					失败:-1
					
					
		4>将系统时间转化为字符串时间
			ctime
			#include <time.h>
			char *ctime(const time_t *timep);
			功能: 
					将系统时间转化为字符串时间 
					
			参数: 
					*timep:保存以秒为单位变量地址 
					
			返回值: 
					成功:字符串时间 
					失败:NULL
					
					
		5>将标准时间转化为可定义的本地时间
		#include <time.h>
		struct tm *localtime(const time_t *timep);
		功能: 
			将标准时间转化为可定义的本地时间
			
		参数: 
			*timep:保存以秒为单位变量地址 
		
		返回值: 
				成功:返回值结构体指针
				失败:返回NULL 
	struct tm {
           int tm_sec;    /* Seconds (0-60) */ 秒数
           int tm_min;    /* Minutes (0-59) */ 分
           int tm_hour;   /* Hours (0-23) */   时
           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 */夏令时 
       };
	   
	   
	   6>将本地时间转化为字符串时间
	   asctime
	   #include <time.h>
	   char *asctime(const struct tm *tm);
	   功能: 
			将本地时间转化为字符串时间
	   参数: 
			tm:结构体指针
	   
	   返回值: 
			成功:字符串时间
			失败:NULL

三、文件IO

核心: 文件描述符
对于系统来说:所有打开的文件,都由文件描述符来引用
文件描述符是一个非负整数,每打开一个文件,内核向进程返回该文件的文件描述符
永远优先分配最小且未被使用的文件描述符

流和文件描述符有什么关系? 
	只有前三个文件描述符和流有关系
	0   1   2 
		
	stdin   stdout  stderr   都是  0   1   2  的链接文件
	操作stdin  等于操作   0 
==============
文件IO的API:应用程序接口 --->函数  

1>打开文件 
    open 
	#include <sys/types.h>
    #include <sys/stat.h>			来源posix
    #include <fcntl.h>
    int open(const char *pathname, int flags);
    int open(const char *pathname, int flags, mode_t mode);
	功能: 
			打开文件  --->文件IO的 
			
	参数: 
			pathname:要打开的文件路径: 相对路径    绝对路径 
			flags:要打开的方式: 
				互斥方式 : 
					O_RDONLY:  	以只读的方式打开文件
					O_WRONLY:	以只写的方式打开文件
					O_RDWR:		以读写的方式打开文件
							这三个方式只能三选一
				多选方式: 
					O_EXCL:使用O_CREAT时.检查文件是否已经存在,用来测试文件是否存在
					O_NOCTTY:使用本参数时,要打开的文件不能是终端
					O_TRUNC:清空模式
					O_APPEND:追加模式
					O_CREAT:如果该文件不存在,则创建,使用该参数,会开启第三参
					:mode 
					
			mode:如果参数2中拥有O_CREAT,则开启
				 用来规定创建文件的权限的  0777  掩码
				 
		返回值: 
			成功返回该文件的文件描述符
			失败返回-1,并返回错误码 

标准IO 文件IO 对比 标准IO的方式和文件IO的方式
fopen open
r O_RDONLY
r+ O_RDWR
w O_WRONLY|O_TRUNC|O_CREAT,0666 - 掩码 0664
w+ O_RDWR|O_TRUNC|O_CREAT,0666 - 掩码 0664
a O_WRONLY|O_APPEND|O_CREAT,0666 - 掩码 066
a+ O_RDWR|O_APPEND|O_CREAT,0666 - 掩码 066

2>读写文件 
	read
	#include <unistd.h>
	ssize_t read(int fd, void *buf, size_t count);
	功能: 
			根据文件描述符,读取数据 
			
	参数: 
			fd:文件描述符     --open返回的 
			buf:读取出来的数据存放的位置
			count:读取数据的大小 	
	
	返回值: 
			成功:返回读取到的字节数
			失败:返回-1,并返回错误码
			读到文件末尾:0

	
	write
	#include <unistd.h>
	ssize_t write(int fd, const void *buf, size_t count);
	功能: 
			写入数据到相应的文件描述符
	参数: 
			fd:文件描述符     --open返回的 
			buf:读取出来的数据存放的位置
			count:读取数据的大小 
			
	返回值: 
		成功:返回写入的字节数 
		失败:返回-1,并返回错误码

3>关闭文件
close
#include <unistd.h>
int close(int fd);
功能:
根据文件描述符,关闭文件

参数: 
		fd:文件描述符 
		
返回值: 
	成功:返回0 
	失败:返回-1,并返回错误码
					2   3  4  5  6   110   95



4>实用函数
	lseek----文件IO的光标偏移 
	有个兄弟 fseek 
			 ftell   ---- 当前光标位置
			 rewind  ---- 光标回到文件头部
	
	lseek
	#include <sys/types.h>
    #include <unistd.h>
    off_t lseek(int fd, off_t offset, int whence);
	功能: 
		对相应的文件描述符的光标进行移动
		
	参数: 
			fd:文件描述符     --open返回的
			offset:偏移量
			whence:基准位置: 
				SEEK_SET:文件头部
				SEEK_CUR:当前位置 
				SEEK_END:文件尾部
				
	返回值: 
			成功返回光标所在位置
			失败返回-1,并设置错误码

4>非格式化IO和格式化IO ----->标准IO

非格式化IO:无法自定义输入输出的格式
	fgetc/getc/getchar 
	fgets/gets
	fread 

	fputc/putc/putchar
	fputs/puts 
	fwrite 
	
格式化IO:自定义输入输出的格式
	printf  
	scanf 
	格式化输出 
	int fprintf(FILE *stream, const char *format, ...);
	//将数据输出到流中
	int sprintf(char *str, const char *format, ...);
	//将格式化字符输出到字符数组中

	格式化输入
	int scanf(const char *format, ...);
    int fscanf(FILE *stream, const char *format, ...);
	//从流中获取数据 
    int sscanf(const char *str, const char *format, ...);
	//从字符串中获取数据 
	
	例子: 
		格式化IO操作流 
		int num;
		char c;
		
		FILE *fp_r=fopen("1.c","r"); 
		FILE *fp_w=fopen("2.c","w");
		
		fscanf(fp_r,"%d %c",&num,&c);
		fprintf(fp_w,"%d %c",num,c);
		
		
		从字符串中获取数据 
		int num;
		char c;
		char buf[64]="28,C";
		
		sscanf(buf,"%d  %c",&num,&c);
		sprintf(buf,"%d  %c",num,c);



文件IO的函数: 
	打开文件 
	 open: 
		需要记住打开的方式
			flags:要打开的方式: 
				互斥方式 : 
					O_RDONLY:   以只读的方式打开文件
					O_WRONLY:	以只写的方式打开文件
					O_RDWR:		以读写的方式打开文件
							这三个方式只能三选一
				多选方式: 
					O_EXCL:使用O_CREAT时.检查文件是否已经存在,用来测试文件是否存在
					O_NOCTTY:使用本参数时,要打开的文件不能是终端
					O_TRUNC:清空模式
					O_APPEND:追加模式
					O_CREAT:如果该文件不存在,则创建,使用该参数,会开启第三参
					:mode 
					
			mode:如果参数2中拥有O_CREAT,则开启
				 用来规定创建文件的权限的  0777  掩码
				 
	读写操作: 
		read 
		
		
		
		write 
		
		
	关闭文件: 
		close 
		
	实用函数: 
		lseek 
		
		dup 
		
		dup2 
			----文件描述符重定向

1>文件和目录属性 —>学习如何使用函数实现ls -l功能
获取文件属性
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

   int stat(const char *pathname, struct stat *statbuf);
   //如果文件为符号链接文件(软链接),则返回本体文件的文件信息
   int fstat(int fd, struct stat *statbuf);
   //需要先打开文件获取文件描述符,才可以获取文件属性
   int lstat(const char *pathname, struct stat *statbuf);
   //如果文件为符号链接文件,则返回符号链接文件的文件信息
   三个函数的返回值:成功返回0,失败返回-1,并设置错误码

struct stat {
dev_t st_dev; /* ID of device containing file /
设备文件
ino_t st_ino; /
Inode number /
inode索引码
mode_t st_mode; /
File type and mode /*
文件类型与权限
nlink_t st_nlink; /
Number of hard links /
硬链接数
uid_t st_uid; /
User ID of owner /
文件拥有者ID
gid_t st_gid; /
Group ID of owner /
文件所属组ID
dev_t st_rdev; /
Device ID (if special file) /
设备号
off_t st_size; /
Total size, in bytes /
文件大小
blksize_t st_blksize; /
Block size for filesystem I/O /
块大小
blkcnt_t st_blocks; /
Number of 512B blocks allocated */
块数

    /* Since Linux 2.6, the kernel supports nanosecond
    precision for the following timestamp fields.
    For the details before Linux 2.6, see NOTES. */

    struct timespec st_atim;  /* Time of last access */
	最后访问时间
    struct timespec st_mtim;  /* Time of last modification */
	最后修改时间
    struct timespec st_ctim;  /* Time of last status change */
	文件状态最后更改时间

       #define st_atime st_atim.tv_sec      /* Backward compatibility */
       #define st_mtime st_mtim.tv_sec
       #define st_ctime st_ctim.tv_sec
       };
通过ID转化为文件拥有者和文件所属组
struct passwd *getpwuid(uid_t uid);
struct passwd {
           char   *pw_name;       /* username */  文件拥有者名称
           char   *pw_passwd;     /* user password */
           uid_t   pw_uid;        /* user ID */
           gid_t   pw_gid;        /* group ID */
           char   *pw_gecos;      /* user information */
           char   *pw_dir;        /* home directory */
           char   *pw_shell;      /* shell program */
       };
	   
	   
所属组
struct group *getgrgid(gid_t gid);
struct group {
           char   *gr_name;        /* group name */ 组名
           char   *gr_passwd;      /* group password */
           gid_t   gr_gid;         /* group ID */
           char  **gr_mem;         /* NULL-terminated array of pointers
                                      to names of group members */
       };

5>文件类型与权限:

该数据来自st_mode

类型与权限:
10位   1+3+3+3
1:文件类型 
第一个3:文件拥有者的权限
第二个3:文件所属组的权限
第三个3:其他用户的权限
解析st_mode

1>目录的属性 ----实现ls操作
1>打开目录
opendir
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:
打开一个目录

			参数: 
					name:目录名
					
			返回值: 
					成功返回DIR *指针
					失败返回NULL,并返回错误码

		2>读取目录
			readdir
		    #include <dirent.h>
			struct dirent *readdir(DIR *dirp);
			功能: 
					读取目录 
			参数: 
					DIR指针   :opendir返回的
					
			返回值:
					成功返回结构体指针
					失败返回NULL,并返回错误码
	struct dirent {
        ino_t          d_ino;       /* Inode number */
		索引码
        off_t          d_off;       /* Not an offset; see below */
		目录文件的偏移
        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]; /* Null-terminated filename */
		文件名
       };
	

		3>关闭目录
			closedir
			#include <sys/types.h>
			#include <dirent.h>
			int closedir(DIR *dirp);
			功能: 	
					关闭目录
			参数: 
					DIR指针
			返回值: 
					成功返回0 
					失败返回-1,并设置错误码

=========================================================================

6>静态库和动态库----函数工具库

	1>什么是库? 
		本质上是某一个代码的二进制形式,可以被载入到内存中执行。
		库一般是别人写好的,现成的,成熟的。
		
		linux和windows不兼容,二者的二进制计算不一样
		
	2>库的分类: 
		静态库和动态库 
		二者的不同点在于代码被载入的时刻不同。
					
		静态库的特点:
		静态库在程序编译时会被连接到目标代码中,
		程序运行时将不再需要该静态库,因此体积较大。
		
		动态库的特点:
		动态库在程序编译时并不会被连接到目标代码中,
		而是在程序运行时才被载入,因此在程序运行
		时还需要动态库存在,因此代码体积较小。

二>实操编写静态库和动态库
静态库:
1>特点
静态库对函数库的链接是放在编译时期(compile time)完成的。
gcc编程的四大步骤:预处理—>编译—>汇编—>链接
优点:程序在运行时与函数库再无瓜葛,移植方便
缺点:浪费空间和资源,因为所有相关的对象文件(object file)与牵涉到的函数
库(library)被链接合成一个可执行文件(executable file)

2>如何创建静态库?
1>第一步:编写一个库源文件:mylib.c
int myplus(int a,int b)
{
return a+b;
}
int myusb(int a,int b)
{
return a-b;
}

2>第二步:将mylib.c编译成.o文件
	gcc -c mylib.c -o mylib.o
	
	ps:-c 对源文件进行编译汇编 但不链接-->不会产生可执行文件

3>第三步: 将.o文件制作成静态库文件   --->静态库命名必须:lib库名.a
	ar crs libmylib.a mylib.o 

ar crs  制作静态库的命令

4>第四步:编写一个测试代码:test.c  用于测试静态库是否可以顺利调用
		#include <stdio.h>
		#include "mylib.h"
		int main(){
			int a,b;
			printf("请输入a和b");
			scanf("%d%d",&a,&b);
			
			
			printf("%d+%d=%d\n",a,b,myplus(a,b));
			printf("%d-%d=%d\n",a,b,myusb(a,b));
			
			
			return 0;
		}
5>第五步: 编译test.c的同时链接静态库
		gcc -Wall -o test test.c -L. -lmylib
		
		-L 找库的路径
		-l 指定库名
		
6>第六步:执行测试
		./test
		请输入a和b10 20
		10+20=30
		10-20=-10

=========================================================================
2>如何创建动态库
1>创建一个库源文件:mylib.c
int myplus(int a,int b)
{
return a+b;
}
int myusb(int a,int b)
{
return a-b;
}

2>将库源文件编译.o 的目标文件
	gcc -fPIC -Wall -c mylib.c 
	
	-fPIC//创建与地址无关的编译程序
	
3>将.o文件制作成动态库文件   库的命名必须:lib库名.so 
	gcc -shared -fPIC -o libmylib.so mylib.o
	
4>编写测试代码: 
	test.c  
	
	
5>编译test的同时链接动态库
	gcc -Wall -o test test.c -L. -lmylib
	
6>发现无法执行---如何让系统认识动态库? 
	1>方法一:一般推荐
			直接将动态库文件放到 /lib 或 /usr/lib  中 
	
	2>方法二:墙裂推荐
			在系统配置文件中声明路径 
			1>打开配置文件
			sudo vim /etc/ld.so.conf 
			
			2>在该文件新行中添加动态库路径
				/home/farsight/shared/IO/day3/dt_LIB

			3>保存退出后执行
				sudo ldconfig 
	
	
	3>方法三:不推荐 
			将动态库的路径声明到环境变量中
	export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/farsight/shared/IO/day3/dt_LIB
		export  --- 声明环境变量 
		LD_LIBRARY_PATH---声明的变量类型是库文件
		
7>三选一后 测试
	./test 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值