常用标准IO:fopen、fclose、fread、fwrite、fseek 学习、使用

系统调用IO函数open,close等都是围绕着文件描述符fd进行相关操作的。
当打开一个文件时,即返回一个文件描述符,然后该文件描述符就用于后续的IO操作。

open系列函数fopen系列函数
常用于打开设备文件常用于打开普通文件
可以指定要创建文件的访问权限不能指定要创建文件的访问权限
open返回一个文件描述符fopen返回一个文件指针
利用文件描述符操纵文件利用文件指针操作文件
POSIX系统调用ANSI C库函数
低层次IO高层次IO,对open的扩展和封装
只能在POSIX操作系统上移植可移植到任何操作系统
非缓冲IO带缓冲IO
只能读取二进制或普通文本可以读取一个结构

而当用C库标准IO函数(fopen、fclose、fread、fwrite、fseek等)打开或创建一个文件时,我们已使一个==流(FILE *stream)==与一个文件相关联了。

fopen打开流

FILE *stream, 文件指针,FILE结构体又被称作流。

#include <stdio.h>
/*
 * @description		: 打开一个文件
 * @param - path	: 指定文件路径,如:"./test.txt"
 * @param - mode	:指定文件的打开方式,如下图:
 * @return 			: 成功,返回指向该文件的文件指针; 若失败,返回	NULL
 */
FILE *fopen(const char *path, const char *mode);

mode参数:

mode说明
“r”打开文本文件用于读
“w”创建文本文件用于写,并删除已存在的内容(如果有的话)
“a”添加;打开或创建文本文件用于在文件末尾写
“rb”打开二进制文件用于读
“wb”创建二进制文件用于写,并删除已存在的内容(如果有的话)
“ab”添加;打开或创建二进制文件用于在文件末尾写
“r+”打开文本文件用于更新(即读和写)
“w+”创建文本文件用于更新,并删除已存在的内容(如果有的话)
“a+”添加;打开或创建文本文件用于更新和在文件末尾写
"rb+“或"r+b”打开二进制文件用于更新(即读和写)
"wb+“或"w+b”创建二进制文件用于更新,并删除已存在的内容(如果有的话)
"ab+“或"a+b”添加;打开或创建二进制文件用于更新和在文件末尾写

当打开一个流时,标准IO函数fopen返回一个指向FILE对象的指针( 文件指针)。
该对象通常是一个结构,它包含了标准IO库为管理该流需要的所有信息(流),
包括用于实际IO 的文件描述符、指向用于该流缓冲区的指针、缓冲区的长度、当前在缓冲区中的字符数以及出错标志等。
为了引用一个流,需将FILE 指针作为参数传递给每个标准IO函数。

fclose关闭流

#include <stdio.h>
/*
 * @description		: 关闭一个已打开的流
 * @param - stream	:文件指针(流)
 * @return 			: 成功,返回0; 若失败,返回EOF
 */
int fclose(FILE *stream); //stream指定的是要关闭的流(文件指针)
//成功返回0;若出错,返回EOF

在该文件被关闭之前,冲洗缓冲中的输出数据。
缓冲区中的任何输入数据被丢弃。如果标准I/O库已经为该流自动分配了一个缓冲区,则释放此缓冲区。
当一个进程正常终止时(直接调用exit函数,或从main函数返回),
则所有带未写缓冲数据的标准IO流都被冲洗,所有打开的标准IO流都被关闭。

fwrite对打开的流写入
#include <stdio.h>
/*
 * @description		: 对已打开的流进行写入数据块
 * @param - ptr		:指向 数据块的指针
 * @param - size	:指定写入的每个数据项的字节数,如调用sizeof(char)
 * @param - nmemb	: 指定写入的数据项的个数
 * @param - stream	:要写入的文件流
 * @return 			: 返回实际写入的数据项的个数
 */
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
fread对打开的流进行读取
#include <stdio.h>
/*
 * @description		: 对已打开的流进行数据读取
 * @param - ptr		:指向 数据块的指针
 * @param - size	:指定读取的每个数据项的字节数
 * @param - nmemb	: 指定要读取的数据项的个数
 * @param - stream	:要读取的文件流
 * @return 			: 返回实际读取数据项的个数;
 */
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

fwrite、fread不能区分文件结尾和错误,调用者必须使用feof函数和ferror函数来确定发生了什么。恩…

fseek定位流
#include <stdio.h>
/*
 * @description		: 重定位文件指针位置
 * @param - stream	:指定重定位文件指针
 * @param - offset	:指定偏移量,整数表示正向偏移,负数表示负向偏移
 * @param - whence	: 指定偏移基准位置,如:宏SEEK_CUR(当前位置)、 SEEK_END(文件结尾) 或 SEEK_SET(文件开头)
 * @return 			: 成功,返回0;  若失败,返回-1,且不改变指针位置。
 */
int fseek(FILE *stream, long offset, int whence);
demo.c
#include <stdio.h>
#include <string.h>

int main(void)
{
    FILE *fp = NULL; 
    int ret;
    char *str = "hello chenchenchen";
    char readBuf[128] = {0};
    fp = fopen("./test.txt", "a+");
    if(fp == NULL){
        printf("Can't fopen file\n");
        return -1;
    }
    printf("fopen file success\n");

    ret = fwrite(str, sizeof(char),strlen(str),fp);
    printf("fwrite byte = %d\n",ret);

	ret = fseek(fp,0,SEEK_SET); 
    if(ret == 0)
    	printf("fseek success\n");
    	   
	ret = fread(readBuf,sizeof(char),strlen(str),fp);
    printf("fread byte=%d, readBuf= %s\n",ret,readBuf);

    ret = fclose(fp);
    if(ret < 0){
        printf("Can't fclose file\n");
        return -1;
    }
    printf("fclose file success\n");

    fp = NULL; /* 防止游离指针 */
    return 0;
}
cxx@ubuntu16:~/C/9_io$ gcc demo.c 
cxx@ubuntu16:~/C/9_io$ ./a.out 
fopen file success
fwrite byte = 18
fseek success
fread byte=18, readBuf= hello chenchenchen
fclose file success

流定向

对于ASCII字符集,一个字符用一个字节表示。对于国际字符集,一个字符可用多个字节表示。
标准I/O文件流可用于单字节或多字节(“宽")字符集。
流的定向(stream’s orientation)决定了所读、写的字符是单字节还是多字节的。
当一个流最初被创建时,它并没有定向。
如若在未定向的流上使用一个多字节I/O函数(见<wchar.h>),则将该流的定向设置为宽定向的。
若在未定向的流上使用一个单字节IO函数,则将该流的定向设为字节定向的。
只有两个函数可改变流的定向。
fwide函数可用于设置流的定向;freopen 函数清除一个流的定向。

#include <wchar.h>
//返回值:若流是宽定向的,返回正值;若流是字节定向的,返回负值;若流是未定向的,返回0
int fwide(FILE *stream, int mode);

mode参数:
如若mode参数值为负,fwide将试图使指定的流是字节定向的.
如若mode参数值为正,fwide 将试图使指定的流是宽定向的(多字节)。
如若mode参数值为0, fwide将不试图设置流的定向,但返回标识该流定向的值。

#include <stdio.h> 
FILE *freopen(const char *path, const char *mode, FILE *stream);

freopen函数:在一个指定的流上打开一个指定的文件,
如若该流已经打开,则先关闭该流。若该流已经定向,则使用freopen清除该定向。
此函数一般用于将一个指定的文件打开为一个预定义的流: 标准输入、标准输出或标准错误。
实现重定向,把预定义的标准流文件定向到由path指定的文件中。
path: 指定存储输入输出的自定义文件路径文件名。
mode:指定文件打开方式。
stream:stdin标准输入、stdout标准输出或stderr标准错误,也对应了最前面的三个文件描述符(0,1,2)。

#include <stdio.h>
FILE *fdopen(int fd, const char *mode);

fdopen函数取一个已有的文件描述符,并使一个标准的IO流与该描述符相结合,转换为对应的文件指针后返回。
mode字符串参数则代表着文件指针的流形态,此形态必须和原先文件描述词读写模式相同。
此函数常用于由创建管道和网络通信通道函数返回的描述符。因为这些特殊类型的文件不能用标准IO函数 fopen 打开,
所以我们必须先调用设备专用函数以获得一个文件描述符,然后用fdopen使一个标准IO流与该描述符相结合。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1. fopen函数原型: ```c FILE *fopen(const char *filename, const char *mode); ``` 使用说明: - filename:文件名,可以是相对路径或绝对路径,需要包含文件扩展名。 - mode:访问模式,可以是 `"r"`(只读)、`"w"`(只写)、`"a"`(追加)、`"rb"`(二进制只读)、`"wb"`(二进制只写)、`"ab"`(二进制追加)等。 返回值: - 成功打开文件返回指向该文件的指针。 - 打开文件失败返回 `NULL`。 2. fclose函数原型: ```c int fclose(FILE *stream); ``` 使用说明: - stream:打开文件的指针。 返回值: - 关闭文件成功返回 0。 - 关闭文件失败返回非 0 值。 3. fread函数原型: ```c size_t fread(void *ptr, size_t size, size_t count, FILE *stream); ``` 使用说明: - ptr:指向要读取数据的缓冲区。 - size:每个数据项的字节数。 - count:要读取的数据项数。 - stream:打开文件的指针。 返回值: - 返回实际读取的数据项数,如果该值小于 count,则可能是读取到了文件末尾或者发生了错误。 4. fwrite函数原型: ```c size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream); ``` 使用说明: - ptr:指向要写入数据的缓冲区。 - size:每个数据项的字节数。 - count:要写入的数据项数。 - stream:打开文件的指针。 返回值: - 返回实际写入的数据项数,如果该值小于 count,则可能是因为磁盘已满或者发生了错误。 5. fseek函数原型: ```c int fseek(FILE *stream, long offset, int whence); ``` 使用说明: - stream:打开文件的指针。 - offset:偏移量,可以是正数或负数,如果是负数则表示向文件开头偏移。 - whence:偏移的位置,可以是 `SEEK_SET`(文件开头)、`SEEK_CUR`(当前位置)、`SEEK_END`(文件结尾)。 返回值: - 执行成功返回 0。 - 执行失败返回非 0 值。 使用注意事项: - 在使用文件 I/O 函数时,需要先打开文件,处理完后再关闭文件。 - 在使用 freadfwrite 函数时,需要注意缓冲区的大小,避免溢出。 - 在使用 fseek 函数时,需要注意偏移量的取值范围,避免越界访问文件。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程一时爽Cxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值