Linux系统编程 1、文件IO、文件属性、文件目录操作函数

Linux系统编程 1、文件IO、文件属性、文件目录操作函数

1. 文件IO函数

1.1 open:打开文件

#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);

参数:
- pathname: 要操作的文件的文件名
- flags: 对文件的操作权限
	必选项: O_RDONLY,  O_WRONLY,  or  O_RDWR, 不能同时用, 只能用一个
	可选项:
		- O_APPEND: 追加, 指定文件文件有写权限的时候可追加
		- O_CREAT: 文件存在不创建, 不存在就创建
		- O_EXCL: 检测文件是否存在, 必须要和O_CREAT一起使用
			O_CREAT | O_EXCL
- mode: 8进制整形数, 0777, 创建出的新文件的权限
	- 实际权限的算法:  (mode & ~umask)
	- 假设: 权限: 0664, umask: 0002, ~umask: 775
           110110100
           111111101
           &
           110110100
            
返回值:
	- 成功: 可用文件描述符
    - 失败: -1

1.2 close:关闭文件

#include <unistd.h>
int close(int fd);			
参数:
	fd: open执行成功得到的文件描述符
	
// 示例程序
// 检测文件是否存在
// 不存在, 创建新文件, 存在返回-1
int fd2 = open("./world.txt", O_RDWR|O_CREAT|O_EXCL, 0777);
printf("fd2 = %d\n", fd2);
if(fd2 == -1) 
{
    
       
    perror("open-world.txt");
}

1.3 read:读文件

// 标准C库, 有缓冲区, 默认8M
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

// Linux系统函数没有缓冲区
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

参数:
	- fd: open文件之后得到的文件描述符, 通过该fd可用找到磁盘文件
	- buf: 存储数据的缓冲区地址(数组地址)
    - count: 缓冲区大小(数组最大容量)
返回值:
	- 成功: 读到的字节数
	- 文件读完了: 返回0
	- 失败: -1

1.4 write:读文件

// 标准C库, 有缓冲区, 默认8k
#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

// Linux系统函数没有缓冲区
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);

参数:
	- fd: open文件之后得到的文件描述符, 通过该fd可用找到磁盘文件
	- buf: 存储了要写的数据
	- count: buf中存储的有效数据的长度
返回值: 
	- 成功: 写入的字节数
	- 什么也没写: 0
    - 失败: -1

1.5 lseek:文件指针偏移

// fseek
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);

// lseek
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

参数:
	- fd: open文件之后得到的文件描述符, 通过该fd可用找到磁盘文件
	- offset: 一个整形的偏移量
	- whence: 
		SEEK_SET: 设置文件指针偏移量, 偏移量就是通过第二个参数指定的
		SEEK_CUR: 当前文件指针偏移量 + 第二个参数指定的偏移
		SEEK_END: 当前文件大小 + 第二个参数指定的偏移
返回值: 文件指针最后的偏移值

// 1. 文件指针移动到文件头(重置文件指针)
lseek(fd, 0, SEEK_SET);
// 2. 获取当前文件指针的位置
lseek(fd, 0, SEEK_CUR);
// 3. 获取文件总大小
lseek(fd, 0, SEEK_END);
// 4. 可以拓展文件大小, 原文件大小100字节, 拓展大小为110, 多出的字节是10
//		使用lseek拓展文件大小, 最后必须进行一次写操作, 才能成功
lseek(fd, 10, SEEK_END);
write(fd, " ", 1);

1.6 perror:查看错误号

查看错误号: 
  /usr/include/asm-generic/errno-base.h
  /usr/include/asm-generic/errno.h
errno: Linux系统函数库中的全局变量, 记录函数调用失败之后的错误号, 每个错误号都有对应的错误描述

// 通过错误号得到错误描述
// 参数: 用户对错误信息的描述, 调用这个函数错误信息会被打印到终端
// 用户描述+系统对错误编号的描述
#include <stdio.h>
void perror(const char *s);

2. 文件属性函数

2.1 access( ):判断文件权限, 或者文件是否存在

// 判断文件权限, 或者文件是否存在
int access(const char *pathname, int mode);
	参数:
		- pathname: 文件名
		- mode: 
			R_OK: 判断文件是不是有读权限
			W_OK: 判断文件是不是有写权限
			X_OK: 判断文件是不是有执行权限
			F_OK: 判断当前文件是否存在
	返回值:
		判断成功: 0, 失败: -1
        文件有判断的权限:0
        文件没有判断的权限:-1

2.2 chmod( ):修改文件权限

// 修改文件权限
// chmod 0777 a.txt
int chmod(const char *filename, int mode);
	参数:
		- filename: 要修改文件权限的文件的名字
		- mod: 八进制数

2.3 chown( ):修改文件所有者

// 修改文件所有者
int chown(const char *path, uid_t owner, gid_t group);
	参数:
		- path: 要修改的文件的名字
		- owner: 用户ID, stat 	/etc/passwd
		- group: 组ID         	/etc/group

2.4 truncate( ):修改文件大小

// 修改文件大小
int truncate(const char *path, off_t length);
	参数: 
		- path: 要操作的文件
		- length: 最终的文件大小
			- length > 源文件大小   ==> 文件拓展, 添加字符0
			- length < 源文件大小   ==> 文件被裁剪, 尾部的被删除

3. 文件目录操作函数

3.1 rename( ):文件重命名

// 文件重命名
int rename(const char *oldpath, const char *newpath);
	参数: 
		- oldpath: 旧的文件名
		- newpath: 新的文件名

3.2 chdir( ):修改进程的工作目录

// 修改进程的工作目录
// 在 /home/lwh启动a.out, a.out的工作目录就是/home/lwh
// chdir("/") -> 进程切换到了根目录
int chdir(const char *path);

3.3 getcwd( ) == pwd命令

// == pwd命令
char *getcwd(char *buf, size_t size);
	参数: 
		- buf: 存储路径, 指向一个由内存大小为size的数组
		- size: 修饰buf大小
	返回值:
		指针指向一块内存, 这个内存就是第一个参数

3.4 mkdir( ):创建目录

// 创建目录
// 如果创建目录, 这个目录必须要有执行权限
int mkdir(const char *pathname, mode_t mode);
	参数:
		- pathname: 目录名
		- mode: 目录的权限 mode & ~umask

3.5 rmdir( ) == rmdir命令, 只能删除空目录 rm -r

// == rmdir命令, 只能删除空目录 rm -r
int rmdir(const char *pathname);

3.6 unlink( ):删除磁盘文件 自动清除缓存

// 删除磁盘文件
// 应用场景举例:自动清除缓存
#include <unistd.h>
int unlink(const char *pathname);
int fd = open("hello.txt", o_rdwr);//举例:假如: 有一个文件hello.txt
unlink("hello.txt");// 这个时候无法删除;当文件被close的时候, 文件才被删除
......;
.......;
close(fd);// 文件才被删除

3.7 opendir:打开目录、readdir:读目录

// opendir的返回类型:是一个保存了文件信息的结构体
struct dirent
{
    
    
    ino_t d_ino;               // 此目录进入点的inode
    ff_t d_off;                // 目录文件开头至此目录进入点的位移
    signed short int d_reclen; // d_name 的长度, 不包含NULL 字符
    unsigned char d_type;      // d_name 所指的文件类型 
    har d_name[256];	       // 文件名
};
d_type
	DT_BLK 	- 块设备
	DT_CHR 	- 字符设备
	DT_DIR 	- 目录
	DT_LNK 	- 软连接
	DT_FIFO - 管道
	DT_REG 	- 普通文件
	DT_SOCK - 套接字
	DT_UNKNOWN - 未知
// 打开目录
DIR *opendir(const char *name);
	参数: 
		name: 要打开的目录
	返回值: 
		成功: 有效指针, 失败: NULL
	// 读目录
  	// 因为一个目录中还有目录, 读目录是递归操作
  	// 读当前目录: 文件是有若干个的, 调用一次readdir只能读一个文件信息, 读所有while()
  	struct dirent *readdir(DIR *dirp);
  		参数:
  			opendir的返回值
  		返回值:
  			一个结构体, 这个对应一个文件

读某个目录下普通文件的个数

// 读某个目录下普通文件的个数
// 需要用到递归, 想明白递归结束的条件
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <string.h>
  #include <dirent.h>
  
  int getFileNums(const char* path)
  {
    
    
      // 打开一个目录
      DIR* dir = opendir(path);
      if(dir == NULL)
      {
    
    
          perror("opendir");
          return 0;
      }
  
      // 记录文件个数
      int count = 0;
      // 读目录
      struct dirent *ptr;
      while( (ptr = readdir(dir)) != NULL)
      {
    
    
          // 如果是. 和 .. 目录直接跳过
          if(strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0)
          {
    
    
              continue;
          }
          // 普通目录要进入到目录内部
          else if(ptr->d_type == DT_DIR)
          {
    
    
              // 进去, 当前目录的子目录
              // path/subName
              char subPath[1024];
              sprintf(subPath, "%s/%s", path, ptr->d_name);
              // 递归调用, 读子目录
              count += getFileNums(subPath); 
          }
          // 如果是普通文件 +1
          else if(ptr->d_type == DT_REG)
          {
    
    
              // 文件个数++
              count ++;
          }
      }
      closedir(dir);
    return count;
  }
  
  int main(int argc, char* argv[])
  {
    
    
  
      int count = getFileNums(argv[1]);
      printf("普通文件个数: %d\n", count);
      return 0;
  }

猜你喜欢

转载自blog.csdn.net/liangwenhao1108/article/details/105564253
今日推荐