当前位置: 首页 > Linux

Linux编程学习笔记-LinuxIO学习[1]——文件IO

时间:2023-04-06 11:55:33 Linux

系统调用与程序运行空间在Linux操作系统中,为了提高系统的稳定性和保证内核的安全,程序运行时的内存空间是分为用户空间和内核空间。普通应用程序工作在用户空间,不能直接访问内核空间。他们需要使用一些“特殊接口”——Linux系统提供给用户的系统调用来安全地访问内核空间。读写文件需要用到Linux系统提供的一些系统调用。在本文中,我主要介绍open()、write()、read()、lseek()和close()等函数,下面我将详细解释这些函数的使用。文件描述符在Linux系统中,一切都可以看作是一个文件,包括:普通文件、目录文件、链接文件和设备文件。要访问文件,必须使用文件描述符。文件描述符是一个非负整数,它是系统上打开的文件的索引。当打开或创建一个文件时,内核会返回一个文件描述符;当它需要读写文件时,还需要将相应的文件描述符作为参数传递给读写函数。程序启动时,默认有3个文件描述符:文件描述符宏描述0STDIN_FILENO标准输入1STDOUT_FILENO标准输出2STDERR_FILENO标准错误输出如果此时创建或打开一个文件,这个文件的文件描述符为3.文件IO基本操作打开/创建文件open()函数用于打开或创建文件。打开或创建文件时,您可以指定各种参数,例如文件属性和用户权限。要使用open()函数,需要包含#include和#include这两个头文件。以下为函数说明:intopen(constchar*path,intoflag,[mode_tmode]);args:constchar*path:文件路径,可以是绝对路径或相对路径intoflag:打开文件的方式-O_RDONLY只读打开-O_WRONLY只写打开-O_RDWR可读可写打开以上三种必须之一被选中,下面四个可以任意选中-O_APPEND追加打开,写入的数据追加到文件末尾-O_CREAT如果文件不存在,则创建它-O_EXCL如果文件存在则报错返回-O_TRUNC如果文件已经存在,以只写或读写方式打开,则将其长度截断为0字节[mode_tmode]:文件权限,仅在创建文件时需要使用return:文件描述符,非负整数表示成功,-1表示失败在open()函数中,打开文件的方式不止以上几种,这里只列出7种常用的。注意新建文件的权限不是直接等于mode的值,而是等于mode&~uname。写入文件打开文件后,我们可以将数据写入文件。在Linux系统中,使用write()向打开的文件写入数据。要使用此功能,您需要包含#include。下面是函数的说明:ssize_twrite(intfildes,constvoid*buf,size_tnbyte);args:intfildes:写入文件的文件描述符constvoid*buf:写入的数据在内存空间中存放的地址size_tnbyte:期望写入数据的最大字节数return:实际写入的字节数文件中,非负整数表示成功,-1表示失败(磁盘已满或超过文件长度等)注意函数的返回类型为ssize_t。ssize_t与size_t类似,只是ssize_t表示有符号数。要了解有关size_t和ssize_t之间区别的更多信息,请参阅本文。读取文件类似于写入文件。要使用文件读取函数read(),您需要包含#include。下面是函数的说明:ssize_tread(intfildes,void*buf,size_tnbyte);args:intfildes:读取文件的文件描述符void*buf:读取数据在内存中的存放地址spacesize_tnbyte:期待读取获取数据的最大字节数return:实际从文件读取的字节数,非负整数表示成功,-1表示失败和write()一样,read的返回类型()函数也是ssize_t。文件偏移量在每个打开的文件中都有一个文件偏移量,文件偏移量会根据文件的读写改变位置。我们可以通过lseek()函数来调整文件的偏移量。默认情况下,新打开文件的文件偏移量位于文件的开头。与write()和read()函数类似,要使用此函数,需要包含#include。以下为函数说明:off_tlseek(intfildes,off_toffset,intwhence);args:intfildes:修改文件的文件描述符off_toffset:文件offset移动的距离intwhence:文件offset的基地址-SEEK_SET文件开头-SEEK_CUR文件当前位置-SEEK_ENDthe文件结束返回:当前文件指针的位置,非负整数表示成功,-1表示失败off_t类似于ssize_t,都是有符号数。关闭文件当文件不再使用时,可以调用close()函数关闭打开的文件。除了使用close()显式关闭文件外,进程打开的所有文件也可以通过终止进程隐式关闭。要使用此功能,需要包含#include。下面是函数的说明:intclose(intfildes);args:intfildes:待关闭文件的文件描述符return:文件关闭状态,0为成功,-1为失败fileIOinstancefilebasicoperation这是一个基本文件操作的简单例子。在本例中,程序将内存中的字符串两次写入文件,然后将文件内容读回内存空间。#include#include#include#include/***这是使用open()、write()、read()的简单示例,lseek()和close()。*/intmain(intargc,char*argv[]){intfd;ssize_twr_size,rd_size;字符缓冲区[128];charstring_1[30],string_2[30]="这是第二行!\n";char*path="./file_io.log";fd=open(path,O_RDWR|O_CREAT|O_TRUNC,511);if(fd<0){printf("文件创建失败...\n");返回-1;}else{printf("文件创建成功...\n");}/*将第一行写入file_io.log*/strcpy(string_1,"Thisisademoforfile_io!\n");wr_size=write(fd,string_1,strlen(string_1));if(wr_size<0){printf("文件写入1失败...\n");printf("wr_size=%d\n",wr_size);返回-1;}else{printf("文件写入1成功...\n");printf("wr_size=%d\n",wr_size);}/*将第二行写入file_io.log*在这种情况下,我们只将string_2中的10字节数据写入文件。*/wr_size=write(fd,string_2,10);/*在第二行末尾添加"\0"(不是'\0'!!)*/wr_size=write(fd,"\0",1);if(wr_size<0){printf("文件写入2失败...\n");printf("wr_size=%d\n",wr_size);返回-1;}else{printf("文件写入2成功...\n");printf("wr_size=%d\n",wr_size);}/*将当前文件偏移减少20个字节*/lseek(fd,-20,SEEK_CUR);rd_size=读取(fd,缓冲区,100);if(rd_size<0){printf("文件read_1失败...\n");printf("rd_size=%d\n",rd_size);返回-1;}else{printf("文件read_1成功...\n");printf("rd_size=%d,\nbuffer=%s\n",rd_size,buffer);}关闭(fd);返回0;}编译运行程序,程序和文件输出如下:对于上面的例子,有几点需要注意:1)在第40行,wr_size=write(fd,字符串_2,10);我们写入的字节数小于string_2中的字节数如果我们要写入的字节数大于string_2中的字节数,那么string_2之外的字节也会被写入文件(这些多余的字节不是我们想要的)。例如,我们将第40行更改为wr_size=write(fd,string_2,100);输出结果如下:2)如果第53行被注释掉,则读取的字节数为0,因为文件的偏移量在文件末尾。CP命令简易版这是一个模仿Linuxcp命令的小程序。这里不考虑效率,也不考虑特殊情况,只是简单的实现了它的功能。#include#include#include#include/**这是cp命令的简单版本。*/intmain(intargc,char*argv[]){intfd1,fd2;ssize_trd_size;字符缓冲区[128];if(argc!=3){printf("你应该输入2个参数\n");返回-1;}fd1=open(argv[1],O_RDONLY);if(fd1<0){printf("文件%d不存在...\n",fd1);返回-1;}fd2=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,511);if(fd2<0){printf("文件%d打开失败...\n",fd2);返回-1;}while(read(fd1,buffer,1))write(fd2,buffer,1);关闭(fd1);关闭(fd2);返回0;}编译运行程序,程序输出如下:总结本文主要介绍如何使用文件IO系统调用函数对文件进行操作,文中出现的代码可以在我的github上找到。如果您觉得本文对您有帮助,请点赞支持,谢谢!