Linux文件操作
来源:互联网 发布:pc蛋蛋杀组合完美算法 编辑:程序博客网 时间:2024/05/19 08:40
一、系统调用
在Linux中,为了更好地保护内核空间,将程序的运行空间分为内核空间和用户空间(也就是常称的内核态和用户态),它们分别运行在不同的级别上,在逻辑上是相互隔离的。
因此,用户进程在通常情况下不允许访问内核数据,也无法使用内核函数,它们只能在用户空间操作用户数据,调用用户空间的函数。简言之,如下图所示:
二、用户编程接口(API)
系统调用并不是直接与程序员进行交互的,它仅仅是一个通过软中断机制向内核提交请求,以获取内核服务的接口。在实际使用中程序员调用的通常是用户编程接口—API,系统命令相对API更高了一层,它实际上一个可执行程序,它的内部引用了用户编程接口(API)来实现相应的功能。
系统命令与系统调用API的关系如下图:
三、Linux文件
1、 Linux中,“一切皆为文件”。在Linux中对目录和设备的操作都等同于对文件的操作,都是使用文件描述符来进行的。Linux文件可分为:普通文件,目录文件,链接文件,设备文件;
2、文件及文件描述符
当打开一个现存文件或创建一个新文件时,内核就向进程返回一个文件描述符fd;当需要读写文件时,也需要把文件描述符作为参数传递给相应的函数。文件描述符是一个非负的整数,它是一个索引值,并指向在内核中每个进程打开文件的记录表。 (举例:买东西需要分票)
一个进程启动时,都会打开3个文件:标准输入、标准输出和标准出错处理。三个文件的文件描述符及对应的宏如下表所示:
文件描述符
宏
标准输入
0
STDIN_FILENO
标准输出
1
STDOUT_FILENO
标准出错
2
STDERR_FILENO
四、不带缓存IO操作
1、创建
(1)函数的作用:创建一个文件;
(2)函数的原型: int creat(const char *pathname, mode_t mode);
(3)函数的参数说明: filename :创建的文件名(包含路径,缺省为当前路径)
mode:创建模式
常创建模式:
S_IRUSR 可读
S_IWUSR 可写
S_IXUSR 可执行
S_IXRWU 可读、可写、可执行
除用以上宏来选择创建模式,也可以用数字来表示,如0666,该八进制数字转化为二进制表示为110(所有者) 110 (同组)110 (其他文件),表示为三组文件都为可读可写。
(4)文件头: #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
(5)返回值:成功:新的文件描述符;
出错: -1
创建几个函数:file_creat.c的函数的编写;
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> void create_file(char *filename){ if(creat(filename,0755)<0){ printf("create file %s failure!\n",filename); exit(EXIT_FAILURE); }else{ printf("create file %s success!\n",filename); } } int main(int argc,char *argv[]){ int i; if(argc<2) { perror("you haven't input the filename,please try again!\n"); exit(EXIT_FAILURE); } for(i=1;i<argc;i++) { create_file(argv[i]); } exit(EXIT_SUCCESS); }
2、打开
(1)函数的作用:打开一个文件;
(2)函数的原型: int open(constchar *pahtname, int flags);
int open(const char *pahtname, int flags, mode_tmode);
注:两者的区别用法为,当用作创建新文件用时,选用第二种。
(3)返回值:文件描述符---成功;出错-1;
(4)头文件:#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
(5)函数的参数:
flags:
以下三个常数中必须指定一个,且仅允许指定一个(这些常数定义在<fcntl.h>头文件中):
O_RDONLY :只读 O_WRONLY:只写 O_RDWR:可读可写
O_CREAT: 如果原来这个文件不存在,那么有这个参数就可以创建这个文件;需同时说明第三个参数mode,用其说明该新文件的存取权限。
O_APPEND:原来有内容,则会自动保留文件内容,自动向下读写;(如不追加,则从文件开始处写)
O_TRUNC: 文件存在,有内容,文件清空;
O_NONBLOCK: 如果pathname指的是一个块特殊文件或一个字符特殊文件,则此选择项为此文件的本次打开操作和后续的I / O操作设置非阻塞方式。
当我们操作完文件以后,需要关闭文件:
int close(int fd);
3、读
(1)函数的原型:ssize_t read(int fd, void *buf, size_tcount);
(2)函数的作用:从文件描述符fd所指定的文件中读取count个字节到buf所指向的缓冲区中。
(3)包含的头文件: #include <unistd.h>
(4)返回值:正常是实际读到的字节数;
如果是在文件结束或者是无数据,返回0;
出错,-1;
写入文件的形式有四种情况:写0,写全部,写部分,出错。
4、写
(1)函数的原型: ssize_t write(int fd, const void *buf, size_t count);
(2)函数的作用:把count个字节从buf指向的缓冲区中写到文件描述符fd所指向的文件中。
(3)头文件: #include <unistd.h>
(4)返回值: 成功会返回实际写入的字节数;
出错:-1;
文件的复制:
#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdlib.h>#define BUFFER_SIZE 1024int main(int argc,char *argv[]){ int from_fd,to_fd; int bytes_read,bytes_write; char buffer[BUFFER_SIZE]; char *ptr; if(argc != 3) { printf("the files are not here!\n"); exit(1); } if((from_fd = open(argv[1],O_RDONLY)) == -1) { printf("open origonal file error!\n"); exit(1); } if((to_fd = open(argv[2],O_WRONLY | O_CREAT,S_IRUSR | S_IWUSR)) == -1) { printf("open target file error!\n"); exit(1); } while(bytes_read = read(from_fd,buffer,BUFFER_SIZE) ) { if(bytes_read == -1) break; else if(bytes_read > 0) { ptr = buffer; while(bytes_write = write(to_fd,ptr,bytes_read)) { if(bytes_write == -1) { break; } else if(bytes_write == bytes_read) break; else if(bytes_write > 0) { ptr += bytes_write; bytes_read -= bytes_write; } } if(bytes_write == -1) break; } } close(from_fd); close(to_fd); exit(0);}
5、定位
(1)函数的原型: int lseek(intfd, offset_t offset, int whence);
(2)函数的作用: 将文件读写指针相对whence移动offset个字节。操作成功时,返回文件指针相对于文件头的位置。
(3)函数的参数:fd:文件标识符
offset: 指针的微调,在指定的指针向前移动为负, 向后为正;
whence: SEEK_SET:放在文件头
SEEK_CUR:当前的位置;
SEEK_END: 文件尾;
(4)返回值:返回文件当前指针到文件开始的地方有多少字节;出错-1;
思考:利用lseek求一个文件的长度:int lseek(int fd,0,SEEK_END);
五.不带缓存的I/O与带缓存的I/O的区别
不带缓存的I/O对是文件描述符操作,带缓存的I/O是针对流的。
标准I/O库就是带缓存的I/O,标准I/O提供缓存的目的就是减少调用read和write的次数,它对每个I/O流自动进行缓存管理(标准I/O函数通常调用malloc来分配缓存)。
它提供了三种类型的缓存:
1) 全缓存。当填满标准I/O缓存后才执行I/O操作。磁盘上的文件通常是全缓存的。
2) 行缓存。当输入输出遇到新行符或缓存满时,才由标准I/O库执行实际I/O操作。stdin、stdout通常是行缓存的。
3) 无缓存。相当于read、write了。stderr通常是无缓存的,因为它必须尽快输出。
一般来说,由系统选择缓存的长度,并自动分配。标准I/O库在关闭流的时候自动释放缓存。在标准I/O库中,一个效率不高的不足之处是需要复制的数据量。
当使用每次一行函数fgets和fputs时,通常需要复制两次数据:
第一次是在内核和标准I/O缓存之间(当调用read和write时), 第二次是在标准I/O缓存(通常系统分配和管理)和用户程序中的行缓存(fgets的参数就需要一个用户行缓存指针)之间。
六、带缓存的I/O操作
1、创建和打开fopen
(1)函数的作用:打开文件
(2)函数的原型: FILE *fopen(const char *pth, const char *mode)
mode:
r:读,文件必须存在;
r+:打开可读写,文件必须存在;
w:打开只写文件,文件不存在就会创建文件;文件已存在,清空重写;
w+:读写方式打开,如果文件不存在则创建,如果文件已存在清空重写
a:附加的形式打开只写文件,不存在就创建,存在就写到原来的文件尾。
a+:以附加的形式打开可读写的文件,不存在就创建,存在就写到原来的文件尾。
b:二进制文件,但Linux不区分二进制文件和文本文件。
(3)文件头: #include <stdio.h>
(4)返回值: 成功是指向=文件流的指针;
出错返回空指针NULL(虽然NULL指针实质为0,但不允许与常数直接比较);
总结:创建一个新文件的方式有三种:create、open函数使用O_CREAT、fopen函数打开方式使用w,w+,a,a+
2.关闭fclose
(1)头文件:#include<stdio.h>
(2)函数原型int fclose(FILE * stream);
(3)函数说明:
fclose()用来关闭先前fopen()打开的文件。此动作会让缓冲区内的数据写入文件中,并释放系统所提供的文件资源
(4)返回值:若成功则返回0,有错误发生时则返回EOF并把错误代码存到errno。
举例:
#include <stdio.h>int main(){ FILE *fp; fp = fopen("target.txt","r+"); if(fp != NULL) { printf("fopen is ok!\n"); } fclose(fp); return 0;}
3.fputc
(1)函数的作用: 将一个指定的字符写入到文件流中;
(2)函数的原型: int fputc(intc, FILE *stream);
(3)返回值: 返回写入成功的字符c; EOF则表示失败。
4.fgetc
(1)函数的作用:从文件流中读取一个字符
(2)函数原型: int fgetc(FILE *stream)
(3)返回值:返回值正常的是读取的字符;EOF表示到了文件尾;
5.fputs
(1)函数的作用:将一个字符串写入到文件内
(2) 函数的原型: int fputs(const char *s, FILE *stream)
(3)返回值:成功返回写成字符数; EOF表示出错
6. fgets
(1)函数的作用:从文件中读取一个字符串;
(2)函数的原型: char *fgets(char *s, int size, FILE *steam)
(3)函数的参数:从stream中读size-1个字符到s中
返回值: 成功返回s, 出错NULL。
7. fread
(1)函数的作用:从文件流中读取数据块
(2)函数原型: size_t fread(void *ptr, size_t size, size_t nmemb, FILE * stream);
(3)返回值: 返回实际读到数据块的数目比nmember小的话,可能是到了文件尾,或者错误发生。
feof :到文件尾;
ferror:判断错误的
8. fwrite
(1)函数的作用:将数据块写到文件流中:
(2)函数原型: size_t fwrite(const void * ptr, size_t size, size_t nmemb, FILE *stream);
(3)函数参数:stream:为已打开的文件指针,ptr: 指向欲写入的数据地址,总共写入的字符数以参数size*nmemb来决定。
(4)返回值: 实际写入的nmemb数目;
#include <stdio.h>#include <string.h>#define set_s(x,y) {strcpy(s[x].name,y);s[x].size = strlen(y);}#define nmemb 3struct test{ char name[20]; int size;}s[nmemb],f[nmemb];int main(){ int i; FILE *stream; set_s(0,"hello"); set_s(1,"world"); set_s(2,"perfect"); stream = fopen("fwrite","w"); fwrite(s,sizeof(struct test),nmemb,stream); fclose(stream); stream = fopen("fwrite","r"); fread(f,sizeof(struct test),nmemb,stream); fclose(stream); for(i = 0;i < nmemb;i++) { printf("f[%d].size:%d ",i,f[i].size);printf("f[%d].name: %s\n",i,f[i].name); }}
11.fseek
(1)函数的作用:移动文件流的读写位置
(2)函数的原型: int fseek(FILE * stream, long offset, int whence)
(3)返回值:成功返回0, 出错-1;
****使用ftell来获取当前的位置;
12. ftell
(1)函数的作用:读取文件流的读写位置;
(2)函数的原型:long ftell(FILE * stream)
(3)返回值: 成功返回当前的读写位置;
出错-1;
13. feof
(1)函数的作用:检测文件流是否到了文件尾
(2)函数的原型:int feof(FILE *stream)
(3)返回值: 非零代表到了文件尾,其他是0;
14. fprintf
(1)函数的作用:格式化数据到文件
(2)函数的原型: int fprintf(FILE *stream, const char *format, ....);
(3)返回值:成功返回实际输入的字符数,失败-1;
15. fscanf
(1)函数的作用: 格式化字符串输入
(2)函数的原型: int fscanf(FILE *strem, const char *fromat,....)
返回值:成功返回参数数目,出错-1
- linux文件操作
- linux文件操作备忘录
- Linux shell__文件操作
- Linux文件操作常用命令
- linux 临时性文件操作
- Linux文件操作篇
- linux文件相关操作
- linux--文件操作命令
- linux 文件操作
- Linux文件基本操作
- linux 文件操作 简介
- linux 文件操作指令
- linux文件操作
- Linux文件操作
- linux文件操作命令
- Linux文件操作
- Linux超大文件操作
- Linux文件操作
- UNIX高编之高级IO
- String、StringBuffer和StringBuilder区别及其常用方法
- 每天一个常用的linux命令(13)--locate
- 64位Win7系统下配置VC/VS调用32位matlab
- Codeforces Round #376 (Div. 2) E
- Linux文件操作
- bzoj 4326: NOIP2015 运输计划 (二分答案+树链剖分+树状数组)
- 栈
- 研一自学unity的心路历程
- MySQL优化之时间类型的选择
- codevs 2292 图灵机游戏(BFS)
- 欢迎使用CSDN-markdown编辑器
- 实施架构一个Android项目
- 进程的相关概念