Linux文件操作(编程)

Linux文件操作

Linux的文件

Linux中对目录和设备的操作都是文件操作,文件分为普通文件,目录文件,链接文件和设备文件

  • 普通文件:也称磁盘文件,并且能够进行随机的数据存储(能够自由seek定位到某一个位置)
  • 管道:是一个从一端发送数据,另一端接收数据的数据通道
  • 目录:也称为目录文件,它包含了保存在目录中文件列表的简单文件
  • 设备:该类型的文件提供了大多数物理设备的接口。它又分为两种类型:字符型设备和块设备。字符型设备一次只能读出和写入一个字节的数据,包括调制解调器、终端、打印机、声卡以及鼠标; 块设备必须以一定大小的块来读出或者写入数据,块设备包括CD-ROM、RAM驱动器和磁盘驱动器 等。**一般而言,字符设备用于传输数据,块设备用于存储数据 **
  • 链接:类似于Windows的快捷方式,指包含到达另一个文件路径的文件。

基于文件指针的文件操作

#include <stdio.h> //头文件包含
FILE* fopen(const char* path, const char* mode);//文件名 模式
int fclose(FILE* stream);
  • fopen以mode的方式打开或创建文件,如果成功,将返回一个文件指针,失败则返回NULL。 fopen创建的文件的访问权限将以0666与当前的umask结合来确定。
  • mode为可选模式列表

文件的读写

数据块的读写

#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);

格式化的读写

#include <stdio.h>
int printf(const char *format, ...);
//相当于fprintf(stdout,format,…);
int scanf(const char *format, …);
int fprintf(FILE *stream, const char *format, ...);
int fscanf(FILE *stream, const char *format, …);
int sprintf(char *str, const char *format, ...);
//eg:sprintf(buf,”the string is;%s”,str);
int sscanf(char *str, const char *format, …);

文件的定位

#include <stdio.h>
int feof(FILE * stream);
//通常的用法为while(!feof(fp)),没什么太多用处
int fseek(FILE *stream, long offset, int whence);
//设置当前读写点到偏移whence 长度为offset处
//whence可以是:SEEK_SET (文件开头)、 SEEK_CUR (文件当前位置)、SEEK_END (文件末尾)
long ftell(FILE *stream);
//用来获得文件流当前的读写位置
void rewind(FILE *stream);
//把文件流的读写位置移至文件开头 fseek(fp, 0, SEEK_SET);

小结

FILE结构体本质上就是一个缓冲区,与FILE类型相关的文件操作(比如fopen,fread等等)称为带缓冲的IO,它们是ISO C的组成部分。fopen实际是对open的封装。

基于文件描述符的文件操作

文件描述符

POSIX标准支持另一类不带缓冲区的IO。在这里,文件是使用文件描述符来描述。文件描述符是一 个非负整数。从原理上来说,进程地址空间的内核部分里面会维护一个已经打开的文件的数组,这个数组用来管理所有已经打开的文件(打开的文件存储在进程地址空间的内核区中,称为文件对象),而文件描述符就是这个数组的索引。因此,文件描述符可以实现进程和打开文件之间的交互。

#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);//文件名 打开方式 权限
  • 新创建的进程都会默认打开3个文件描述符,分别占用0,1,2,其中0代表标准输入流、1代表标准输出流、2代表标准错误流。在编程中通常使用宏STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO分别来代表0,1,2。
  • 执行成功时,open函数返回一个文件描述符(自动选择最小可用的文件描述符),表示已经打开的文件;执行失败是,open函数返 回-1,并设置相应的errno

文件的读写

#include <unistd.h>

ssize_t read(int fd, void *buf, size_t count);

fd:文件描述符

buf:要读入的缓冲区

count:最多读多少个字节

对于返回值:

#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);

二进制数据的处理

对比

open和fopen

open和fopen分别对应着两种文件系统:无缓冲文件系统和带缓冲文件系统。

  • open函数是系统调用,返回的是文件描述符。文件描述符是一个非负整数,它是UNIX/Linux下的一个概念,从原理上来说,进程地址空间的内核部分里面会维护一个已经打开的文件的数组,这个数组用来管理所有已经打开的文件(打开的文件存储在进程地址空间的内核区中,称为文件对象),而文件描述符就是这个数组的索引。因此,文件描述符可以实现进程和打开文件之间的交互。
  • fopen函数是C语言的库函数,它返回的是一个文件指针(一个指向文件结构体的指针)。fopen是ANSI C标准中的C语言库函数,在不同的OS中会调用不同的内核API,UNIX环境下,fopen是对open的封装。文件结构体FILE本质是一个缓冲区。
  • fopen用户态下就有了缓冲,它使用了FILE这个结构保存缓冲数据。在进行读和写的时候减少了用户态和内核态的切换。open没有缓存,每次读操作都直接从文件系统中获取数据。在进行读和写的时候每次都需要进行内核态和用户态的切换。故,如果顺序访问文件,fopen系列的函数要比直接调用open系列快;如果随机访问文件open要比fopen快。

带缓冲的文件IO

这种方式是通过FILE结构体作为一个缓冲区,将内存中的数据读到该缓冲区中,再通过文件对象来进行操作,这种方式可以减少用户态和内核态之间的切换次数。

不带缓冲的文件IO

使用不带缓冲IO的时候,CPU需要陷入内核态来处理文件读取。如果频繁地使用read来读取少量数据,数据的读取效率会比较低。故使用不带缓冲的文件IO时可以将buf设置大一点。

posted @ 2023-03-22 21:49  MyXjl  阅读(86)  评论(0编辑  收藏  举报