标准I/O

本文介绍了C语言的标准I/O库,包括fopen、fclose、freopen等文件操作函数,以及fgetc、fputc、fflush等功能,强调了缓冲机制在提高效率中的作用,并通过示例展示了如何读写文件和管理流指针。
摘要由CSDN通过智能技术生成

介绍

标准I/O是C语言库,不仅在UNIX系统,在其他操作上也可以使用。

标准I/O在系统调用函数基础上构造的,增加了一个缓冲机制,它便于用户使用。


#include <stdio.h>

 

FILE *fopen(const char *path, const char *mode);
 
功能:打开文件

参数:
        path:文件的路径

        mode:打开方式
                r 或 rb:

                        打开只读文件,该文件必须存在。
                r+ 或 rb+:

                        打开可读写的文件,该文件必须存在。
                w 或 wb:

                        以写的方式打开文件,文件不存在,则创建。文件存在,则清空。
                w+ 或 wb+:

                        以读写的方式打开文件,文件不存在,则创建。文件存在,则清空。
                a 或 ab:

                        以追加的方式打开文件(写),文件不存在,则创建。

                        文件存在,则再文件的末尾追加。
                a+ 或 ab+:

                        以追加的方式打开文件(读写),文件不存在,则创建。

                        文件存在,则再文件的末尾追加。          

返回值:   
        成功: FILE * (流指针 === 结构体指针)
        失败: NULL

 

注意:当给定 “b” 参数时,表示以二进制方式打开文件。

FILE:系统会自动为使用的文件在内存中开辟一片空间,来存储文件的详细信息,这个空间的数据类型为结构体类型。

FILE *:流指针,在标准I/O中,每次打开一个文件都会返回一个流指针,我们也得用同样类型的FILE *去接收这个流指针,这个流指针则描述了一个文件,所有的标准I/O都是围绕着文件来进行的。

同一个文件可以存在多个流指针。标准I/O函数测试当前系统最大能打开的文件个数为1021,其实为:1024。因为在系统中我们使用的输入、输出、错误提示都是文件。这三个文件分别是:标准输入流、标准输出流、标准错误流,占了1024里的0、1、2。

打开我们的终端时系统就默认打开了3个流指针:

  • stdin (标准输入,终端进行输入)
  • stdout(标准输出,终端打印出来)
  • stderr(标准错误,终端打印出来)

int fclose(FILE *fp);

 
功能:关闭fopen打开的文件
参数:
        fp:流指针

为什么要关闭一个文件?

  1. 防止其它进程操作这个文件
  2. 释放掉这个结构体的占用的资源

FILE *freopen(const char *path, const char *mode, FILE *stream);

 
功能:改变流指针的指向
参数:
        path:文件的路径名
        mode:打开方式
        stream:流指针


int fgetc(FILE *stream);

 
功能:读取一个字节的数据
参数:
        stream:流指针
返回值:
        成功:返回这个字节
        失败:-1

int fputc(int c, FILE *stream);

 
功能:写入一个字节的数据
参数:
        c:字节
        stream:流指针

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

/**
 * 向终端循环打印'X'
 */
int main(int argc, char *argv[])
{
    // 因为每一个终端都是一个文件: pts/xxx 这个就是终端对应的文件。
    // 这个文件的名字是以数字命名的,存储在 : /dev/pts/xxx 这些文件是由linux系统自动创建。
    // 当打开一个终端时,就会重建一个新的文件与之对应 stdin、stdout、stderr 都指向的是同一个文件(终端文件)。
    FILE *fp = fopen("/dev/pts/1", "r+"); // 以读写的方式打开我们新开的终端文件

    if (NULL == fp)
    {
        perror("fopen"); // 判断返回值
        return -1;
    }

    while (1)
    {
        fputc('x', fp); // 调用函数fputc循环打印x
        fputc('\n', fp);
        sleep(2); // 用延时函数2秒打印一个
    }

    return 0;
}

int fflush(FILE *stream);

 
功能:将缓冲区中的内容写到stream所指的文件中去。

           若stream为NULL,则会将所有打开的文件进行数据更新。
参数:
        stream:流指针

fflush(stdin):刷新缓冲区,将缓冲区内的数据清空并丢弃。
fflush(stdout):刷新缓冲区,将缓冲区内的数据输出到设备。


char *fgets(char *s, int size, FILE *stream);

 
功能:从文件读取一行的数据并且写入到内存空间
参数:
        s:内存地址,也可以在内存上定义一片空间
        size:内存空间的大小 N
        stream:流指针
返回值:
        成功:返回读取字符的首地址
        失败:NULL

int fputs(const char *s, FILE *stream);

 
功能:向文件写入一行数据
参数:
        s:内存地址,开辟的存储空间已经有数据存在
        stream:流指针
返回值:
        成功:1
        失败:-1

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

/**
 * copy指令:把一个文件的内容复制到另一个文件内
 */
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        printf("%s src_file dest_file\n", argv[0]); // 如果命令行参数少于3个,则打印提示信息
    }

    FILE *fp1 = fopen(argv[1], "r"); // 定义第一个流指针,命令行第二个参数写文件名,打开这个文件
    if (NULL == fp1)
    {
        perror("fopen");
        return -1;
    }

    FILE *fp2 = fopen(argv[2], "w"); // 定义第二个流指针,命令行第二个参数写文件名,打开这个文件
    if (NULL == fp2)
    {
        perror("open");
        return -1;
    }

    char buf[100] = {0}; // 我们从第一文件读的数据得存储到内存
    while (1)
    {
        char *p = fgets(buf, sizeof(buf), fp1); // 判断函数是否成功执行
        if (NULL == p)
        {
            // 读取最后跳出循环
            printf("while break\n");
            break;
        }
        fputs(buf, fp2); // 把内存的内容写入到第二个流指针打开的文件中
    }

    printf("Copy Sucess..\n");
    fclose(fp1);
    fclose(fp2);

    return 0;
}

int fseek(FILE *stream, long offset, int whence);

 
功能:定位文件指针
参数:
        stream:流指针
        offset:偏移量 
                100:向后偏移100个字节
                -100:向前偏移100个字节
        whence:基点 
                SEEK_SET:文件开头
                SEEK_END:文件末尾
                SEEK_CUR:文件当前位置
返回值:
        成功:0
        失败:-1

 
例:
        定位到文件末尾:fseek(fp, 0, SEEK_END);
        定位到文件末尾的前一个字节:fseek(fp, -1, SEEK_END);

long ftell(FILE *stream);

 
返回值:当前文件指针的位置(大小)

void rewind(FILE *stream);

 
功能:文件指针返回到文件开头

#include <stdio.h>

int main(int argc, char *argv[])
{
    FILE *fp = fopen("./1.txt", "r+");
    if (NULL == fp)
    {
        perror("fopen");
        return -1;
    }

    int ret = fseek(fp, 0, SEEK_END); // 把指针移动到文件末尾

    int n = ftell(fp); // 统计文件的大小,也就算统计文件的位置。返回字节数
    printf("文件的大小(字节):%d \n", n); // 结果:文件大小

    rewind(fp); // 把文件的指针返回到文件的开头

    int m = ftell(fp);
    printf("文件的大小(字节):%d \n", m); // 指针返回到文件开头再来看指针的位置。结果:0

    return 0;
}

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

 
功能:读取数据(可以读取二进制、字符数据)
参数:
        ptr:内存地址  eg: char ptr[];
        size:字节数
        nmemb:块数
        stream:流指针
返回值:
        成功:块数
        失败:-1

char buf[1000] = {0};
​
函数的用法(可用于读取普通数组或结构体数组):
fread(buf, 100, 10, fp); // 读取1000个字节的数据
​
fread(buf, 10, 100, fp);
​
fread(buf, 1, 1000, fp);
​
fread(buf, 1000, 1, fp);
​
fread(buf, 20, 50, fp);
.......
#include <stdio.h>

int main(int argc, char *argv[])
{
    FILE *fp = fopen("./1.txt", "rb"); // 二进制方式读取文件
    if (NULL == fp)
    {
        perror("fopen");
        return -1;
    }

    char buf[100] = {0};
    int n = fread(buf, 100, 1, fp); // 读取文件到BUF

    printf("%d \n", n);
    printf("%s \n", buf);
    fclose(fp);

    return 0;
}

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

 
功能:写入数据(可以写入二进制、字符数据)
参数:
        ptr:内存地址  eg: char ptr[];
        size:字节数
        nmemb:块数
        stream:流指针
返回值:
        成功:块数
        失败:-1

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

struct A
{
	int m;
	float n;
	char ch;
};

int main(int argc, const char *argv[])
{
	// printf("%d\n", sizeof(struct A));

	struct A a = {10, 3.14, 'b'};

	struct A b;

	printf("%d\n", sizeof(a));

	FILE *fp = fopen("./1.txt", "wb+"); // 打开文件,注意这里的打开方式为读写,W后面有个b是说明二进制文件。
	if (NULL == fp)
	{
		perror("fopen");
		return -1;
	}

	// 结构体信息写入文件。
	fwrite(&a, sizeof(struct A), 1, fp);

	printf("write success!\n");

	// 因为上面的写入函数执行后,就把文件的指针移位了,这里使用rewind函数使文件指针回到文件的开头。
	rewind(fp);

	// 如果不执行上一步操作的话,这里的fread就不会从文件开头读并写入到结构体b中。
	fread(&b, sizeof(struct A), 1, fp);

	// 打印结构体b的数据。
	printf("%d %.2f %c\n", b.m, b.n, b.ch);

	fclose(fp);

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值