ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

linux(C/C++)下的文件操作: open、fopen与freopen

2020-12-25 18:01:56  阅读:219  来源: 互联网

标签:文件 FILE C++ 描述符 mode freopen linux include open


open是linux下的底层系统调用函数,fopen与freopen c/c++下的标准I/O库函数,带输入/输出缓冲。

linxu下的fopen是open的封装函数,fopen最终还是要调用底层的系统调用open。
所以在linux下如果需要对设备进行明确的控制,那最好使用底层系统调用(open)

  • open对应的文件操作有:close, read, write,ioctl 等。
  • fopen 对应的文件操作有:fclose, fread, fwrite, freopen, fseek, ftell, rewind等。
  • freopen用于重定向输入输出流的函数,该函数可以在不改变代码原貌的情况下改变输入输出环境,但使用时应当保证流是可靠的

open和fopen的区别:

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

1、open、close系统调用(linux)

理论

#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 	
/*
* 返回:若成功则为新文件描述符,若出错为-1
*/
int open( const char * pathname, int oflags);			
int open(char *filename, int flags, mode_t mode); 
						

#include <unistd.h> 
/*
* 返回:若成功则为 o, 若出错则为 -1(关闭一个已关闭的描述符会出错)
*/
int close(int fd);
						

1、功能:open 函数将 filename 转换为一个文件描述符,并且返回描述符数字。返回的描述符总是在进程中当前没有打开的最小描述符

2、参数:
pathname 是待打开/创建文件的路径名
flags 参数指明了进程打算如何访问这个文件:

• O_RDONLY: 只读
• O_WRONLY: 只写。
• O_RDWR: 可读可 写。

以上三者是互斥的,即不可以同时使用。至少得使用上述三个常量中的一个

以读的方式打开一个已存在的文件:

fd = open("foo.txt", O_RDONLY, 0);

flags 参数也可以上面的一个| 下面的零个或者多个:
• O_CREAT: 如果文件不存 ,就创建它的一个截断的 (truncated) (空)文件
• O_TRUNC: 如果文件巳经 在,就截断它
• O_APPEND: 在每次 操作前,设置文件位置到文件的结尾处

打开一个已存在文件,并在后面添加一些数据:
fd = open("foo .txt", O_ ONLYIO_APPEND, 0);

mode 参数仅当创建新文件时才使用(而且必须用),用于指定文件的访问权限。
在这里插入图片描述
作为上下文的一部分,每个进程都会有一个umask、它是通过调用unmask函数来设置的。

当进程通过带某个 mode 参数的 open 函数调用来创建一个新文件时,文件的访问权
限位被设置为mode & ~ umask

2、返回值:

成功则返回文件描述符,否则返回 -1。 返回文件描述符(整型变量0~255)。由open 返回的文件描述符一定是该进程尚未使用的最小描述符。只要有一个权限被禁止则返回-1。

错误代码:

EEXIST 参数pathname 所指的文件已存在,却使用了O_CREAT和O_EXCL旗标。
EACCESS 参数pathname所指的文件不符合所要求测试的权限。
EROFS 欲测试写入权限的文件存在于只读文件系统内。

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

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

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

实践

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main ()
{
    int fd1, fd2;

    fd1 = open("a.txt", O_RDONLY, 0);
    printf("fd1 = %d\n", fd1);
    close(fd1);
    fd2 = open("b.txt", O_RDONLY, 0);
    printf("fd2 = %d\n", fd2);
    close(fd2);
    return(0);
}

现象: 如果文件不存在,返回-1。
如果文件存在,返回3
在这里插入图片描述

分析: Linux shell创建的每个进程开始时都有三个打开的文件:标准输入(描述符为 0) 、标准输出(描述符为 1) 和标准错误(描述符为 2), open返回的描述符总是在进程中当前没有打开的最小描述符。

fopen、freopen、fclose库函数

理论

#include<stdio.h>
/*
* 作用: 使用给定的模式 mode 打开 filename 所指向的文件
* 参数:
* 	filename -- 这是 C 字符串,包含了要打开的文件名称。
*   mode -- 这是 C 字符串,包含了文件访问模式
* 返回值: 该函数返回一个 FILE 指针。否则返回 NULL,且设置全局变量 errno 来标识错误。
*/
FILE *fopen(const char *filename, const char *mode)

/*
* 作用:把一个新的文件名 filename 与给定的打开的流 stream 关联,同时关闭流中的旧文件。
* 参数:
* 	filename -- 这是 C 字符串,包含了要打开的文件名称。
*   mode -- 这是 C 字符串,包含了文件访问模式
*   stream -- 这是指向 FILE 对象的指针(文件指针),该 FILE 对象标识了要被重新打开的流。通常使用标准流文件(stdin/stdout/stderr)
* 返回值: 如果成功则返回该指向该stream的指针,否则为NULL。
*/
FILE *freopen(const char *filename, const char *mode, FILE *stream)

/*
* 作用:  关闭流 stream。刷新所有的缓冲区。
* 参数:  stream -- 这是指向 FILE 对象的指针,该 FILE 对象指定了要被关闭的流。
* 返回值: 如果流成功关闭,则该方法返回零。如果失败,则返回 EOF
*/
int fclose(FILE *stream)

mode取值
在这里插入图片描述

  • “r"或"rb” 以只读方式打开文件,该文件必须存在。
  • “w"或"wb” 以写方式打开文件,并把文件长度截短为零。
  • “a"或"ab” 以写方式打开文件,新内容追加在文件尾。
  • "r+"或"rb+“或"r+b” 以更新方式打开(读和写)
  • "w+"或"wb+“或"w+b” 以更新方式打开,并把文件长度截短为零。
  • "a+"或"ab+“或"a+b” 以更新方式打开,新内容追加在文件尾。

字母b表示文件时一个二进制文件而不是文本文件。(linux下不区分二进制文件和文本文件)

实践

freopen使用

#include <stdio.h>
#include <string.h>

int main ()
{
    FILE *fp;

    printf("该文本重定向到 stdout \n");

    fp = freopen("file.txt", "w+", stdout); // 关联标准输出 STDOUT 到文件 file.txt

    printf("该文本重定向到 file.txt dddddddddddddd\n");
    fclose(fp);
    return(0);
}

在这里插入图片描述

fclose封装

void Fclose(FILE *fp)
{
    if (fclose(fp) != 0){
        printf("fclose error");
        exit(0);
    }
}

标签:文件,FILE,C++,描述符,mode,freopen,linux,include,open
来源: https://blog.csdn.net/zhizhengguan/article/details/111693888

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有