_011_linux下用c语言调用文件操作函数

时间:2021-07-24 01:09:09

==============================================================

open的文章摘自https://www.cnblogs.com/fnlingnzb-learner/p/7040726.html

下面就对上面的文章进行简化修改

 

open和fopen的区别


  1,fread是带缓冲的,read不带缓冲.
  2,fopen是标准c里定义的,open是POSIX中定义的.
  3,fread可以读一个结构.read在linux/unix中读二进制与普通文件没有区别.
  4,fopen不能指定要创建文件的权限.open可以指定权限.
  5,fopen返回文件指针,open返回文件描述符(整数).

 

open系统调用(linux)


  需要包含头文件:

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

 

  函数原型

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

 

mode仅当创建新文件时才使用,用于指定文件的访问权限

 

pathname 是待打开/创建文件的路径名;

 

oflags用于指定文件的打开/创建模式

   O_RDONLY       只读模式 
   O_WRONLY      只写模式 
   O_RDWR          读写模式

以上三者是互斥的,即不可以同时使用。

 

打开/创建文件时,至少得使用上述三个常量中的一个。以下常量选用,选用方式O_RDONLY|O_APPEND
   O_APPEND         每次写操作都写入文件的末尾 
   O_CREAT            如果指定文件不存在,则创建这个文件 
   O_EXCL               如果要创建的文件已存在,则返回 -1,并且修改 errno 的值,所以要判断文件是否存在,要O_CREAT和O_EXCL一起用
   O_TRUNC           如果文件存在,并且以只写/读写方式打开,则清空文件全部内容 
   O_NOCTTY         如果路径名指向终端设备,不要把这个设备用作控制终端。
   O_NONBLOCK   如果路径名指向 FIFO/块文件/字符文件,则把文件的打开和后继 I/O设置为非阻塞模式(nonblocking mode)。
//以下用于同步输入输出
   O_DSYNC          等待物理 I/O 结束后再 write。在不影响读取新写入的数据的前提下,不等待文件属性更新。 
   O_RSYNC          read 等待所有写入同一区域的写操作完成后再进行
   O_SYNC            等待物理 I/O 结束后再 write,包括更新文件属性的 I/O

 

第三个参数mode
这些标志在头文件sys/stat.h中定义,和文件的权限是一样的,可以用数字来代替,比如0777,0是代表8进制

但是填写了第3个参数后,得出来的文件的权限依然不是我们指定的,因为会有一个掩码,这个0777会和掩码取反后进行与的计算

得到实际权限,umask可以显示掩码,umask 数字 可以修改掩码,以下完全可以用数字代替
  S_IRUSR:    读权限,文件属主
  S_IWUSR:   写权限,文件属主
  S_IXUSR:    执行权限,文件属主
  S_IRGRP:    读权限,文件所属组
  S_IWGRP:   写权限,文件所属组
  S_IXGRP:    执行权限,文件所属组
  S_IROTH:   读权限,其它用户
  S_IWOTH:  写权限,其它用户
  S_IXOTH:   执行权限,其它用户

 

返回值:成功则返回文件描述符,否则返回 -1。  返回文件描述符(整型变量0~255)
错误代码
  EEXIST 参数pathname 所指的文件已存在,却使用了O_CREAT和O_EXCL旗标。
  EACCESS 参数pathname所指的文件不符合所要求测试的权限。
  EROFS 欲测试写入权限的文件存在于只读文件系统内。

EFAULT 参数pathname指针超出可存取内存空间。

 EINVAL 参数mode 不正确。
  ENAMETOOLONG 参数pathname太长。

 ENOTDIR 参数pathname不是目录。
  ENOMEM 核心内存不足。
  ELOOP 参数pathname有过多符号连接问题。
  EIO I/O 存取错误

 


 write函数

  #include <unistd.h>

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

  参数:   
  fd:要进行写操作的文件描述词。
  buf:需要输出的缓冲区
  count:最大输出字节计数  

  返回值:成功返回写入的字节数,出错返回-1并设置errno

 

 


 read函数

  #include <unistd.h>

  ssize_t read(int fd, void *buf, size_t count);  
  参数:      
  buf:需要读取的缓冲区
  count:最大读取字节计数 

  返回值:成功返回读取的字节数,出错返回-1并设置errno,如果在调read之前已到达文件末尾,则这次read返回0 。

 

 


 

以下摘自:https://blog.csdn.net/songyang516/article/details/6779950

lseek函数

   #include <sys/types.h>

  off_t lseek(int filedes, off_t offset, int whence);

  返回值:新的偏移量(成功),-1(失败)

  所有打开的文件都有一个当前文件偏移量(current file offset),以下简称为 cfo。cfo 通常是一个非负整数

 

  参数 offset 的含义取决于参数 whence:

  1. 如果 whence 是 SEEK_SET,文件偏移量将被设置为 offset。
  2. 如果 whence 是 SEEK_CUR,文件偏移量将被设置为 cfo 加上 offset,
         offset 可以为正也可以为负。
     3. 如果 whence 是 SEEK_END,文件偏移量将被设置为文件长度加上 offset,
         offset 可以为正也可以为负。

 

  SEEK_SET、SEEK_CUR 和 SEEK_END 使用之前是 0、1 和 2。

 

  lseek 的以下用法返回当前的偏移量:

    off_t    currpos;
        currpos = lseek(fd, 0, SEEK_CUR);

 

  lseek还有一个作用,就是文件的扩展,但是文件扩展需要对文件最后进行一次写的操作

  lseek(fd, 2000, SEEK_END);

  write(fd,"a",1);

 


 以下摘自:https://www.cnblogs.com/sylar5/p/6491033.html

stat函数

  #include <sys/stat.h>  

  #include <unistd.h>

  int stat(const char *file_name, struct stat *buf);

  函数说明:    通过文件名filename获取文件信息,并保存在buf所指的结构体stat中

  返回值:      执行成功则返回0,失败返回-1,错误代码存于errno

  错误代码

 

ENOENT         参数file_name指定的文件不存在
    ENOTDIR        路径中的目录存在但却非真正的目录
    ELOOP          欲打开的文件有过多符号连接问题,上限为16符号连接
    EFAULT         参数buf为无效指针,指向无法存在的内存空间
    EACCESS        存取文件时被拒绝
    ENOMEM         核心内存不足
    ENAMETOOLONG   参数file_name的路径名称太长

  stat的使用

 

 1 #include <sys/stat.h>
 2 #include <unistd.h>
 3 #include <stdio.h>
 4 
 5 int main() {
 6     struct stat buf;
 7     stat("/etc/hosts", &buf);
 8     printf("/etc/hosts file size = %d\n", buf.st_size);
 9 }
10 
11 /*************************************************************************/
12 struct stat {
13     dev_t         st_dev;       //文件的设备编号
14     ino_t         st_ino;       //节点
15     mode_t        st_mode;      //文件的类型和存取的权限
16     nlink_t       st_nlink;     //连到该文件的硬连接数目,刚建立的文件值为1
17     uid_t         st_uid;       //用户ID
18     gid_t         st_gid;       //组ID
19     dev_t         st_rdev;      //(设备类型)若此文件为设备文件,则为其设备编号
20     off_t         st_size;      //文件字节数(文件大小)
21     unsigned long st_blksize;   //块大小(文件系统的I/O 缓冲区大小)
22     unsigned long st_blocks;    //块数
23     time_t        st_atime;     //最后一次访问时间
24     time_t        st_mtime;     //最后一次修改时间
25     time_t        st_ctime;     //最后一次改变时间(指属性)
26 };

 

 

 

 

  lstat函数类似于stat,但是当命名的文件是一个符号连接时,lstat返回该符号连接的有关信息,而不是由该符号连接引用的文件的信息

 


 

摘自:https://blog.csdn.net/tigerjibo/article/details/11712039

access函数

  #include <stdio.h> 
  #include <unistd.h>

  int access(const char * pathname, int mode);

  pathname:需要检测的文件路劲名
  mode:需要测试的操作模式

  成功执行时,返回0。失败返回-1,errno被设为以下的某个值 
  EINVAL: 模式值无效 
  EACCES: 文件或路径名中包含的目录不可访问 
  ELOOP : 解释路径名过程中存在太多的符号连接 
  ENAMETOOLONG:路径名太长 
  ENOENT:路径名中的目录不存在或是无效的符号连接 
  ENOTDIR: 路径名中当作目录的组件并非目录 
  EROFS: 文件系统只读 
  EFAULT: 路径名指向可访问的空间外 
  EIO:输入输出错误 
  ENOMEM: 不能获取足够的内核内存 
  ETXTBSY:对程序写入出错

 

  mode说明

  R_OK 测试读许可权 
  W_OK 测试写许可权 
  X_OK 测试执行许可权 
  F_OK 测试文件是否存在

 


 

摘自:https://blog.csdn.net/cy_cai/article/details/21599147

truncate函数

  #include <unistd.h>

  int truncate(const char *path, off_t length);

  truncate("/aaa",500);

  函数说明:truncate()会将指定的文件大小改为参数length指定的大小.如果原来的文件大小比参数length大,则超过的部分会被删除

 


 unlink函数

  #include <unistd.h>

  int unlink(const char *oldpath)

  oldpath:源文件路径名

  返回值:
  成功返回0;失败返回-1,其错误存在全局变量errno中,可用perror查看
  

  函数说明:

  如果文件是一个符号链接,那么删除符号链接,如果是硬链接,硬链接数-1,当减为0的时候,直接删除文件(当然必须有写的权限)

  如果硬链接数为0,且已经打开这个文件,那么只有当这个文件关闭了,且没有其他用户操作这个文件的时候才会去删除

  所以可以利用这个特性去创建一个临时文件

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<sys/types.h>
 4 #include<unistd.h>
 5 #include<fcntl.h>
 6 
 7 int main()
 8 {
 9    int fd=open("tempfile",O_CREAT | O_RDWR,0644);//打开并创建一个文件(文件不存在的情况下)
10     if(fd==-1)
11    {
12         perror("open"); //perror会打印出错误的信息
13         exit(1); 
14     }
15     
16     int ret=unlink("tempfile"); //删除临时文件,等文件操作完才会删除
17     
18      write(fd,"hello\n",6);
19 
20       lseek(fd,0,SEEK_SET);
21 
22      char buf[24]={0};
23 
24      int len=read(fd,buf,sizeof(buf));
25 
26      write(1,buf,len);//将内容写到屏幕上,1是out,也就是屏幕
27      close(fd);
28 }

 


 

目录操作函数

  #include <unistd.h>

  int chdir(const char*path);

  说明:chdir函数用于改变当前工作目录。调用参数是指向目录的指针,调用进程需要有搜索整个目录的权限

        改变的是程序中改变的那个路径,而不是我们终端界面的

 

  char *getcwd(char *buf, size size)

  说明:获取当前程序所在进程的目标,buf是存放的目标的字符数组,size就是要存放多少长度

 

  int mkdir(const char *pathname, mode_t mode)

  说明:创建一个目录,mode是模式,可以用数字代替,比如0777

 

  include< dirent.h>

  DIR *opendir(const char *dirpath);

  说明:打开一个目标,返回DIR结构指针,这个结构保存所打开的目录信息

  struct dirent* readdir(DIR* dir_handle);

  说明: 参数传入opendir的返回值,返回一个结构,可以用closedir关闭

struct dirent
{
long d_ino; /* inode number 索引节点号 */
off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
unsigned short d_reclen;/* length of this d_name 文件名长 */
unsigned char d_type; /* the type of d_name 文件类型 */
char d_name [NAME_MAX+1];/* file name (null-terminated) 文件名,最长255字符 */
}

  d_type的类型,可以通过这个判断文件的类型

_011_linux下用c语言调用文件操作函数

=

递归的例子

 

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <sys/types.h>
 4 #include <dirent.h>
 5 #include <string.h>
 6 
 7 int getFilename(char *root)
 8 {
 9      //打开目录
10     DIR *dir = NULL;
11     int total = 0;
12     if (dir == NULL)
13     {
14         perror("opendir");
15         exit(1);
16     }
17 
18     char mypath[1024] = { 0 };
19     dir = opendir(root);
20     struct  dirent* ptr = NULL;
21     while ((ptr = readdir(dir)) != NULL) //判断是否目录为空
22     {
23         //过滤.和..
24         if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..")==0)
25         {
26             continue;
27         }
28 
29         //如果是目录
30         if (ptr->d_type==DT_DIR)
31         {
32             //递归读取目录
33             sprintf(mypath, "%s/%s", root, ptr->d_name);
34             //计算读取了多少个目录
35             total = total+getFilename(mypath);
36         }
37              //如果是普通文件,计算
38         if (ptr->d_type == DT_REG)
39             {
40             total++;
41             }
42     }
43 
44     closedir(dir);
45     return total;
46 }
47 
48 int main(int argc,char*argv[])
49 {
50     if (argc < 2)
51     {
52         printf("a.out. dir\n");
53         exit(1);
54     }
55     int total = getFilename(argv[1]);
56     printf("%d\n", total);
57     return 0;
58 }

 


 

 摘自:https://www.cnblogs.com/sherlockhomles/archive/2013/05/20/3089212.html

dup&dup2函数

  dup函数的作用:复制一个现有的句柄,产生一个与“源句柄特性”完全一样的新句柄(也即生成一个新的句柄号,并关联到同一个设备)

  dup2函数的作用:复制一个现有的句柄到另一个句柄上,目标句柄的特性与“源句柄特性”完全一样

          (也即首先关闭目标句柄,与设备断连,接着从源句柄完全拷贝复制到目标句柄)

 


 

fcntl函数

  #include <unistd.h>

  #include <fcntl.h>

  int fcntl(int fd, int cmd);

  int fcntl(int fd, int cmd, long arg); 

  int fcntl(int fd, int cmd, struct flock *lock);

  函数说明: 现阶段只使用第二种和第一种, 

  cmd先阶段只需要了解2个状态

  F_GETFL     取得fd的文件状态标志,如同下面的描述一样(arg被忽略)   这是第一种,只获取

  F_SETFL     设置给arg描述符状态标志,可以更改的几个标志是:O_APPEND, O_NONBLOCK,O_SYNC和O_ASYNC。

        这是第二种,改变文件的状态,状态填写在第三个参数