Linux文件操作API新手村介绍

(一)Linux 文件操作API

(1)Linux文件操作常见API

在 Windows 系统中,对文件的打开或是编辑都是可视化的,其具体的操作流程可归纳为:
打开或创建文件 ——> 编辑文件 ——> 保存文件 ——> 关闭文件
在 Linux 系统中,一切皆文件,包括但不限于硬件设备、管道、数据库、Socket等;操作系统对文件的处理提供了一系列API程序接口,常用的包括:

API功能
open打开文件
creat创建文件
read读取文件
write写入文件
lseek移动光标
close关闭文件

(2)常见API使用说明

使用这些API时,并不需要准确记住用法,只需要记住名称,使用man指令进行查找即可(man手册在Linux中绝对好用,适合小白),例如我们需要了解open函数如何调用,可在Linux 终端(Ctrl+Alt+T)输入“man 2 open”,即open函数在man手册中的第2页,会弹出对应的man手册。

lamda@lamda-virtual-machine:~/Desktop/code/Linux/File$ man 2 open

手册中关于open函数的描述如下,附带需要的头文件以及函数原型:

OPEN(2)                                               Linux Programmer's Manual                                              OPEN(2)

NAME
       open, openat, creat - open and possibly create a file

SYNOPSIS
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <fcntl.h>

       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode);

       int creat(const char *pathname, mode_t mode);

       int openat(int dirfd, const char *pathname, int flags);
       int openat(int dirfd, const char *pathname, int flags, mode_t mode);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       openat():
           Since glibc 2.10:
               _POSIX_C_SOURCE >= 200809L
           Before glibc 2.10:
               _ATFILE_SOURCE

DESCRIPTION
       The  open()  system  call  opens the file specified by pathname.  If the specified file does not exist, it may optionally (if
       O_CREAT is specified in flags) be created by open().

open 函数的原型常用的有两个,再加上creat函数:

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);

其中,pathname是指文件路径,是指向char类型的指针,可用字符串表示,mode表示文件权限,flags为文件操作使用权限,包括:

flags描述
O_RDONLY只读
O_WRONLY只写
O_RDWR可读可写
O_CREAT若文件不存在,可创建新文件,并需要提供第三个参数mode描述文件权限
O_EXCL如果同时指定了OCREAT,而文件已经存在,则出错
O_APPEND每次写时都加到文件的尾端
O_TRUNC如果这个文件中本来是有内容的,而且为只读或只写成功打开,则将其长度截短为0

显然,前三个只能指定一个,函数中第三个参数mode表示文件权限,包括:

宏表示数字描述
S_IRUSR4可读
S_IWUSR2可写
S_IXUSR1可执行
S_IRWXU7可读、可写、可执行

open函数会返回一个int类型的值,通常称为文件描述符,read或write函数则是通过这个文件描述符对文件进行编辑,文件描述符只能在当前进程下使用。同样通过man手册查阅如何调用read或write函数:

ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
off_t lseek(int fd, off_t offset, int whence);

(3)Linux文件操作常见API使用示例

  接下来我们简单使用C语言程序完成上述API完成文件的创建以及编辑。
// 需要的头文件
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h> 
      
//ssize_t write(int fd, const void *buf, size_t count);
//ssize_t read(int fd, void *buf, size_t count);
//off_t lseek(int fd, off_t offset, int whence);

int main()
{
    char buf[128] = "Write something for test!";
	int fd;
	fd = open("./file_demo",O_RDWR);   //可读可写方式
	if(fd==-1){                        //检测是否存在,若不存在则创建
	printf("This file maybe not exist.\n");
	fd = open("./file_demo",O_CREAT,S_IRWXU);  //0600,文件可读可写
	}
	int num_write = write(fd,buf,strlen(buf));   //写入内容
        printf("Write %d bytes.\n",num_write);
	int num_seek = lseek(fd,0,SEEK_SET);   
	//移动光标,因为写入内容后光标并不在文件头,需要重新调整到文件头进行读取
	char *readbuf;
	readbuf = (char *)malloc(num_write*sizeof(char));
    int num_read  = read(fd,readbuf,num_write);
	printf("Read %d bytes.\n",num_read);
	printf("%s\n",readbuf);
	num_seek = lseek(fd,0,SEEK_CUR);
	printf("num_seek = %d\n",num_seek);
	close(fd);    //关闭文件
  	return 0;
}

(二)C语言标准库文件操作API

(1)C语言标准库文件操作常见API

这里简单描述标准库里的API

API功能
fopen打开文件
fseek移动光标
fread读取文件
fwrite写入文件
fclose关闭文件
fgetc读取字符
fputc写入字符
feof判断是否到达文件尾,否则返回0

(2)open与fopen的区别

参考博文:总结open与fopen的区别
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函数,后者属于高级IO函数。低级和高级的简单区分标准是:谁离系统内核更近。低级文件IO运行在内核态,高级文件IO运行在用户态。

5. 缓冲

缓冲文件系统
缓冲文件系统的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用;当执行读文件的操作时,从磁盘文件将数据先读入内存“缓冲区”,装满后再从内存“缓冲区”依此读出需要的数据。执行写文件的操作时,先将数据写入内存“缓冲区”,待内存“缓冲区”装满后再写入文件。由此可以看出,内存“缓冲区”的大小,影响着实际操作外存的次数,内存“缓冲区”越大,则操作外存的次数就少,执行速度就快、效率高。一般来说,文件“缓冲区”的大小随机器 而定。fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等。
非缓冲文件系统
缓冲文件系统是借助文件结构体指针来对文件进行管理,通过文件指针来对文件进行访问,既可以读写字符、字符串、格式化数据,也可以读写二进制数据。非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度快,由于ANSI标准不再包括非缓冲文件系统,因此建议大家最好不要选择它。open, close, read, write, getc, getchar, putc, putchar等。

(3)C语言标准库文件操作常见API使用示例

同样地,我们使用C语言进行操作:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
//FILE *fopen(const char *pathname, const char *mode);
  FILE *fp;
  char *str = "Fopen:write something.";
  char *readbuf = NULL;
  readbuf = (char*)malloc(strlen(str));
  fp = fopen("./file_fopen","r+");
  printf("open file is ok\n");
  //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);
  int n_write = fwrite(str,sizeof(char),strlen(str),fp);
  printf("write something is ok\n");
  fseek(fp,0,SEEK_SET);
  int n_read = fread(readbuf,sizeof(char),strlen(str),fp);
  printf("read something: %d bytes, %s\n",n_read,readbuf);	
  fclose(fp);
  return 0;
}

(三)总结

  1. 在使用write函数后一定记得使用lseek函数对光标进行定位,否则在原文件继续读取可能会出错。
  2. 文件描述符一般会从3开始,原因是0,1,2,分别被内核的相关操作所占用,分别为标准输入,标准输出,标准错误输出
  3. read和write函数所操作的文本内容的都是无类型指针,意味着可以输入整型或是其他类型,如结构体、链表等。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值