Linux文件输入输出
文件打开open、文件写入write、文件读取read、文件关闭close、文件光标lseek、文件创建create
文件一般流程是打开或者创建文档——编辑文档——保存文档——关闭文档。liunx文件操作所提供的api(Application Programming Interface,应用程序接口)有open、write、read、close、lseek、create等。
文件打开open
open头文件和函数
// open头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//open函数
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
//open函数返回值,success 返回文件描述符, error 返回 -1
//pathname:文件路径名。例"./file1"
//flags:O_RDONLY 只读 O_WRONLY 只写 O_RDWR 可读可写可打开
// O_CREAT 如果open文件不存在,则创建文件。
// O_EXCL 如果同时指定了OCREAT,而文件已经存在,则open()出错,返回-1。
// O_APPEND 每次文件写入加到文件尾部。
// O_TRUNC 删去文件中原本的内容。
//mode: 一定是在flags中使用了O_CREAT标志,mode记录待创建的文件的访问权限。
mode的分类和加权数字表示
| 宏表示 | 含义 | 宏表示 | 含义 | 宏表示 | 含义 |
|---|---|---|---|---|---|
| S_IRUSR | 使用者可读权限 | S_IRGRP | 群组拥有读权限 | S_IROTH | 其他用户拥有读权限 |
| S_IWUSR | 使用者可写权限 | S_IWGRP | 群组拥有写权限 | S_IWOTH | 其他用户拥有写权限 |
| S_IXUSR | 使用者可执行权限 | S_IXGRP | 群组拥有执行权限 | S_IXOTH | 其他用户拥有执行权限 |
S_IRUSR、S_IWUSR、S_IXUSR比较常用
| 加权数字 | 第一位 | 第二位 | 第三位 |
|---|---|---|---|
| 4 | 使用者可读权限 | 群组拥有读权限 | 其他用户拥有读权限 |
| 2 | 使用者可写权限 | 群组拥有写权限 | 其他用户拥有写权限 |
| 1 | 使用者可执行权限 | 群组拥有执行权限 | 其他用户拥有执行权限 |
例如:0666,拥有4+2=6使用者可读、可写权限;拥有4+2=6群组可读、可写权限;拥有4+2=6其他用户可读、可写权限。
什么是文件描述符?简单来说就是描述和区分文件的一个标志。上面看出文件描述符是个int型。
什么是程序?什么进程?
1、程序是静态的概念,gcc xxx.c –o pro 磁盘中生成pro文件,叫做程序;
2、进程是程序的一次运行活动,通俗点意思是程序跑起来了,系统中就多了一个进程;
ps:图中fd为文件描述符,图中进程和原进程是一个意思,由于为让图结构看着清晰,取了原进程的名字。
open函数综合举例:
int fd = open("./file1", O_RDWR|O_CREAT, 0600);open函数综合举例
文件写入write
write头文件和函数
// write头文件
#include <unistd.h>;
//write函数
ssize_t write(int fd, const void *buf, size_t count);
//函数含义:从buf中写count字节大小的数进入fd的文件里。
//返回 success 返回 整型数 = 写入的字节数; error 返回 -1
write函数综合举例:
char *buf ="linux write";
write(fd, buf, sizeof(buf));`write函数综合举例`
文件读取read
read头文件和函数
// read头文件
#include <unistd.h>;
//read函数
ssize_t read(int fd, const void *readbuf, size_t count);
//函数含义:从fd的文件中读出count字节大小的数进入readbuf。
//返回 success 返回 整型数 = 写入的字节数; error 返回 -1
read函数综合举例:
read(fd, buf, sizeof(buf));`read函数综合举例`
文件关闭close
close头文件和函数
// close头文件
#include <unistd.h>;
//read函数
ssize_t close(int fd);
//函数含义:关闭fd文件。
close函数综合举例:
close(fd);`close函数综合举例`
文件光标seek
每次读取或者写入后,光标的位置的位置不确定。为了确定光标位置,可以使用lseek()函数。
lseek头文件和函数
// lseek头文件
#include <unistd.h>;
#include <sys/type.h>;
//lseek函数
off_t lseek(int fd, off_t offset, int whence);
//函数含义:依据whence的定位偏移offset的位数;
//whence:SEET_SET 文件头
// SEEK_CUR 当前光标位置
// SEEK_END 文件尾
//offset: offset 正数往后移,负数往前移
//返回 success 返回 当前光标位置与文件头偏移字节数; 失败 返回 -1
lseek函数综合举例:
lseek(fd, 0, SEEK_END);`lseek函数综合举例`
文件创建create
create头文件和函数
// creat头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//creat函数
int creat(const char *pathname, mode_t mode);
//函数含义:依据whence的定位偏移offset的位数;
//pathname:文件路径名。例"./file1"
//返回 success 返回 文件标识符; 失败 返回 -1
| 宏表示 | 含义 |
|---|---|
| S_IRUSR | 使用者可读权限 |
| S_IWUSR | 使用者可写权限 |
| S_IXUSR | 使用者可执行权限 |
| S_IRWXU | 使用者可读可写可执行权限 |
creat函数综合举例:
creat(fd, S_IRWXU);`creat函数综合举例`
动态文件和静态文件
静态文件指的是存在磁盘中的文件。
动态文件指的是open打开静态文件后,Linux内核产生结构体,结构体中包含文件标识符fd、信息节点、buf等,然后close关闭,才可以变回静态文件。
ps:比较两个程序异同vimdiff 文件名 文件名
实战举例一:cp拷贝代码的编写
思路
1、打开src.c
2、读src.c到buf
3、打开des.c
4、写buf到des.c
5、close两个文件
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv)//argc是命令行总的参数个数
//**argv=*argv[]是argc个参数,其中第0个参数是程序的全名,以后的参数命令行后面跟的用户输入的参数
{
int fdSrc;//打开源文件文件标识符
int fdDec;//打开目标文件文件标识符
if(argc !=3){
printf("param error\n");
exit(-1);
} //判断输入参数是否正确
fdSrc=open(argv[1],O_RDWR,0600);
int size = lseek(fdSrc,0,SEEK_END); //计算文件大小
lseek(fdSrc,0,SEEK_SET); //重置文件光标
char *readBuf=(char* )malloc(sizeof(char)*size + 8);
int n_read=read(fdSrc,readBuf,size);
fdDec=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0600);//创建可读可写可执行、删除原本文件内容
int n_write = write(fdDec,readBuf,size);
close(fdSrc);
close(fdDec);
return 0;
}
实战举例二:配置文件参数
思路:
1、找到a的位置
2、a往后移到b
3、修改b的内容
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int fdSrc;
if(argc != 2){
printf("param error\n");
exit(-1);
}
fdSrc=open(argv[1],O_RDWR,0600);
int size = lseek(fdSrc,0,SEEK_END);
lseek(fdSrc,0,SEEK_SET);
char *readBuf=(char* )malloc(sizeof(char)*size + 8);
int n_read=read(fdSrc,readBuf,size);
char *p = strstr(readBuf,"LENG=");//字符串查找函数
if(p==NULL){
printf("not found\n");
}
p=p+strlen("LENG="); //字符串计算函数
*p='5';
lseek(fdSrc,0,SEEK_SET);
int n_write = write(fdSrc,readBuf,size);
close(fdSrc);
return 0;
}
扩展知识——比较fopen系列与open系列函数区别
1、来源
open是UNIX系统调用函数(包括LINUX等),返回的是文件描述符(File Descriptor),它是文件在文件描述符表里的索引。
fopen是ANSIC标准中的C语言库函数,在不同的系统中应该调用不同的内核api。返回的是一个指向文件结构的指针。
2、移植性
fopen是C标准函数,因此拥有良好的移植性;而open是UNIX系统调用,移植性有限。如windows下相似的功能使用API函数CreateFile。
3、适用范围
open返回文件描述符,而文件描述符是UNIX系统下的一个重要概念,UNIX下的一切设备都是以文件的形式操作。当然包括操作普通正规文件(Regular File)。fopen是用来操纵普通正规文件(Regular File)的。
4、文件IO层次
低级和高级的简单区分标准是:谁离系统内核更近。低级文件IO运行在内核态,高级文件IO运行在用户态。open属于低级IO函数,fopen属于高级IO函数。
5、缓冲
缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用;当执行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”,装满后再从内存“缓冲区”依此读出需要的数据。执行写文件的操作时,先将数据写入内存“缓冲区”,待内存“缓冲区”装满后再写入文件。
非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度快。
简单来说。缓冲文件系统需要缓冲区转换,非缓冲文件系统直接实现内核态和用户态的转换。当下内存都比较大,两种模式的运行速度快慢区别不大。
fopen头文件和函数
头文件:#include <stdio.h>
函数:FILE *fopen(const char *path, const char *mode);
fread和fwrite头文件和函数
头文件: #include <stdio.h>
函数: size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
函数: size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
fseek和fseek头文件和函数
头文件: #include <stdio.h>
函数:int fseek(FILE *stream, long offset, int whence);
参数解释
void *ptr:指向被读取(写入)的元素数组指针
size_t size:要被读取(写入)的元素数组大小,以字节为单位
size_t nmemb:元素的个数,以size为单位
FILE *stream:指向FILE对象的指针
到此结束,师承上官可编程;