第二天————文件IO

文件IO
文件IO的特点:
1.文件IO是POXIC(可移植操作系统接口)定义的一组函数
2.不提供缓冲机制,每次读写都会引起系统调用
3.文件描述符,是一个非负整数,文件描述符是0开始的
标准IO默认打开3个文件
stdin 标准输入 0
stdout 标准输出 1
stderr 标准出错 2

4.Linux下,标准IO基于文件IO实现
文件的打开和关闭
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
参数1:文件名(可包含路径)
参数2:打开方式
O_RDONLY 以只读方式打开文件
O_WRONLY 以只写方式打开文件
O_RDWR 以读写方式打开文件
O_CREAT 如果该文件不存在,就创建一个新的文件
并用第三参数为其设置权限
O_TRUNC 如果文件存在,那么打开文件时先删除文件中原有数据
O_EXCL 如果该文件存在,则报错
O_APPEND 以添加方式打开文件,所以对文件的写操作都在文件的末尾进行
O_NOCTTY
第三个参数:文件的权限 0777

返回值:成功返回文件描述符,若失败,则返回-1
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

#include <unistd.h>
int close(int fd);
在这里插入图片描述
在这里插入图片描述

文件掩码:
在这里插入图片描述

0777
0 111 111 111 0 111 111 111
& ~ 000 000 010 & 111 111 101
_______________
111 111 101 775
文件的读写
函数功能:从fdz这个文件读取count个字节读到buf指向的空间中
#include <unistd.h>
参数1:文件描述符
参数2:空间的首地址
参数3:一次性读取多少个字节
返回值:成功返回具体的个数,失败则返回-1,
返回0表示到达文件末尾或无可读取的数据
ssize_t read(int fd, void *buf, size_t count);
在这里插入图片描述

函数功能:将buf指向空间中count个字节写入到fd这个文件中
参数1:文件描述
参数2:首地址
参数3:写入的字节数
返回值:成功具体写入的字节数
ssize_t write(int fd, const void *buf, size_t count);
在这里插入图片描述

作业:模拟cp命令 (复制照片)
1------以只读方式打开文件1.png给fr open()
2------以只写方式打开文件2.png给fw open()
3------从fr中读取n个字节给buf read()
4------将读到的n个字节写入到fw中去 write()
5------循环3,4,直到n==0
6------关闭fr,fw close()

文件其他相关函数

#include <sys/types.h>
#include <unistd.h>
函数功能:移动文件指针
参数1:文件描述符
参数2:偏移量
参数3:位置 SEEK_SET
SEEK_CUR
SEEK_END
off_t lseek(int fd, off_t offset, int whence);
空洞文件
1.什么是空洞文件?
“在UNIX文件操作中,文件位移量可以大于文件的当前长度,在这种情况下,对该文件的下一次写将延长该文件,并在文件中构成一个空洞,这一点是允许的。位于文件中但没有写过的字节都被设为 0。”
2.空洞文件有什么用?
例如:迅雷下载文件时,在未下载完成时就已经占据了全部文件大小的空间,这时候就是空洞文件。下载的时候如果没有空洞文件,多线程下载时文件就都只能从一个地方写入,这就不是多线程了。如果有了空洞文件,可以从不同的地址写入,就完成了多线程的优势任务。

如何创建一个空洞文件
1.以只写的方式打开该文件
2.移动文件指针,移动1G
3.在末尾写一个字节
4.关闭文件

#include <stdio.h>
#include "io.h"//包含了用到函数的头文件
int main(int argc, const char *argv[])
{
	//1.以只写方式打开文件
	//2.移动文件指针
	//3.在末尾写一个字节
	//4.关闭文件
	int fw=0;
	//1.以只写方式打开文件
	fw=open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0666);

	if(fw<0)
	{
		perror("open error");
		return -1;
	}

	//2.移动文件指针
	lseek(fw,1024*1024*1024,SEEK_SET);
	//3.在末尾写一个字节
	write(fw,"\0",1);
	
	close(fw);

	return 0;
}

目录打开和关闭
#include <sys/types.h>
#include <dirent.h>
参数1: 目录名
返回值: 成功返回DIR *,失败则返回NULL
DIR *opendir(const char *name);

#include <sys/types.h>
#include <dirent.h>
int closedir(DIR dirp);
目录的读取
struct dirent {
ino_t d_ino; /
inode number /
off_t d_off; /
offset to the next dirent /
unsigned short d_reclen; /
length of this record /
unsigned char d_type; /
type of file; not supported
by all file system types /
char d_name[256]; /
filename */ —>文件名
};

#include <dirent.h>
参数1:打开的目录指针
返回值:成功struct dirent *,失败则返回NULL
struct dirent *readdir(DIR *dirp);
ls -a
在这里插入图片描述

ls
在这里插入图片描述

获得文件的属性
stat/lstat/fstat 获得文件属性
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
fstat参数是文件描述符,不建议使用
int fstat(int fd, struct stat *buf);
int stat(const char *path, struct stat *buf);
int lstat(const char *path, struct stat *buf);
如果path是符号链接,stat获得是目标文件的属性
lstat获得的是链接文件的属性
参数1:文件名(绝对路径)
参数2: struct stat * 获得文件属性之后,将文件属性的值放到buf所指的空间
返回值:若失败则返回-1
int lstat(const char *path, struct stat *buf);
ls -l
#include <stdio.h>
以某种格式显示在屏幕上
int printf(const char *format, …);
printf(“%s/%s”,argv[1],pd->d_name); “/home/linux/1.c“
以某种格式显示到文件中
int fprintf(FILE *stream, const char *format, …);
fprintf(fp,“%s/%s”,argv[1],pd->d_name);
以某种格式存入到文件中去
char path_name[100];
int sprintf(char *str, const char *format, …);
sprintf(path_name,”%s/%s”,argv[1],pd->d_name);
在这里插入图片描述

struct stat {
dev_t st_dev; /* ID of device containing file /
ino_t st_ino; /
inode number /
mode_t st_mode; /
protection /
nlink_t st_nlink; /
number of hard links /
uid_t st_uid; /
user ID of owner /
gid_t st_gid; /
group ID of owner /
dev_t st_rdev; /
device ID (if special file) /
off_t st_size; /
total size, in bytes / ---->文件的大小
blksize_t st_blksize; /
blocksize for file system I/O /
blkcnt_t st_blocks; /
number of 512B blocks allocated /
time_t st_atime; /
time of last access /
time_t st_mtime; /
time of last modification /
time_t st_ctime; /
time of last status change */
};
在这里插入图片描述

静态库和动态库的区别:
静态库:
编译时把静态库中的相关代码复制到可执行程序中
优点:
程序运行时无需加载库,运行速度更快
缺点:
占用更多磁盘和内存空间
静态库升级后,需要重新编译链接
动态库:
编译时仅记录用到哪个共享库中的哪个符号,不复制共享库中的相关代码
优点:
程序不包含库中代码,体积比较小
库升级方便,无需重新编译
缺点:
在运行需要加载共享库
创建静态库
1.编写源代码:
vim filelength.c
vim fileline.c
2.生成相应的.o文件
gcc -c fileLine.c -o fileLine.o
gcc -c filelength.c -o filelength.o
3.创建成相应的静态库
静态库的命名方式 lib+库名.a
ar rcs libfile.a fileLine.o filelength.o
ar—>用来创建静态库
r ---->在库中插入模块
c---->创建一个库,不管库是否存在,都将创建
s---->创建目标文件索引,这在创建较大的库时能加快时间
4.编译时链接静态库
在这里插入图片描述
在这里插入图片描述

5.运行
在这里插入图片描述
在这里插入图片描述

创建动态库
1.编写源文件
vim filelength.c
vim fileLine.c
2.生成相应的.o文件
gcc -c -fPIC filelength.c -o filelength.o
gcc -c -fPIC fileLine.c -o fileLine.o
-fPIC 要生成位置无关代码,可以在任何位置执行

3.生成动态库(共享库)
动态库的命名方式: lib+库名.so.版本号 用数字来表示版本号
gcc -shared -o libfile.so.1 filelength.o fileLine.o
4.为共享库文件创建软链接文件
创建链接文件的目的就是为了能够让我们扥的编译器在编译时找到共享库
ln -s libfile.so.1 libfile.so
5.编译会链接共享库(同时指名库路径)
gcc test.c -o test -L. -lfile
6.运行时需要链接动态库
会去系统库路径动态库
在这里插入图片描述

7.将动态库复制到 /lib,/usr/lib
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值