美文网首页
标准I/O库

标准I/O库

作者: suntwo | 来源:发表于2019-06-21 10:26 被阅读0次

文件的操作

文件的基本操作通常有读写增加操作,我们使用C语言的标准库来对文件进行操作使用fopen函数进行打开文件,打开文件操作实际上操作系统会为这个文件分配资源,为文件分配文件描述符和I/O缓冲区等资源。使用fclose函数来进行关闭文件,这两个是成对使用的,如果没有关闭文件在进程执行完毕时也会自动关闭文件,但是如果是一个长期运行的进程,如果打开过多的文件,会占用很多的资源,因此这两个函数要成对使用。

fopen函数

#include <stdio.h>

FILE *fopen(const char *path, const char *mode);
返回值:成功返回文件指针,出错返回NULL并设置errno
  • 这个函数有两个参数,第一个表示文件的路径可以是相对路径,也可以是绝对路径。
  • 第二个参数表示打开文件的方式,可以是读写添加。
  • 返回类型是一个FILE类型的结构体指针。
  • 使用这个函数打开文件之后,我们可以通过使用返回的文件句柄来进行操作文件。

FILE类型

  • 这个类型是C标准库中定义的一个结构体
  • 这个结构体中有从内核中对这个文件的文件描述符来标识这个打开的文件,还有对这个文件的I/O缓冲区和当前文件的读取位置等信息。
  • 这个类型里的成员我们通常是不需要操作的,对我们是隐藏的,我们只需要将FILE *类型的变量传递给其他的文件操作函数便可以对文件进行操作。

mode参数的介绍

这个参数传递进来的是一个字符串,传递不同的值有不同的操作。

  • r 表示以只读的方式打开文件,打开之前这个文件必须存在。
  • w 表示以只写的方式打开,打开后会截断原来的内容,从开始写入,如果文件不存在会自动创建文件。
  • a 表示以添加的方式打开,在文件的末尾进行添加内容,如果文件不存在会创建文件。
  • r+ 表示以读写的方式打开文件,文件必须是存在的。
  • w+ 表示以读写的方式打开文件,打开后会截断原来的内容,从开始写入,如果文件不存在会自动创建文件。
  • a+ 允许读和追加数据,如果文件不存在则创建。

fclose函数

#include <stdio.h>

int fclose(FILE *fp);
返回值:成功返回0,出错返回EOF并设置errno

表示关闭文件,关闭系统分配给这个文件的资源,关闭后不能再操作这个文件。

stdin/stdout/stderr

这三个其实也是FILE *类型的,在一个终端打开时会自动打开这三个句柄,这三个可以向终端输入数据和输出数据,和文件的读取类似。

  • stdin表示读取我们向终端输入的数据,比如scanf函数,读物我们输入的内容。
  • stdout表示从终端显示我们输出的内容,比如printf函数,输出信息。
  • stderro表示从终端显示错误信息。
    我们操作这三个句柄想操作文件一样。

errno与perror函数

在libc中定义了errno这个全局变量,使用这个变量表示程序的错误信息,当一个程序出错时便会将errno设置为一个整数,来对应一个错误信息,但是如果只有一个整数是不能看出错误信息的,因此我们可以使用perror或者strerror函数来将错误信息打印出来。

#include <stdio.h>

void perror(const char *s);
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    FILE *fp = fopen("abcde", "r");
    if (fp == NULL) {
        perror("Open file abcde");
        exit(1);
    }
    return 0;
}
结果:
root@ubuntu:/home/sun/project# ./bb
Open file abcde: No such file or directory
#include <string.h>

char *strerror(int errnum);
返回值:错误码errnum所对应的字符串

以字节为单位的读入读出

#include <stdio.h>

int fgetc(FILE *stream);
int getchar(void);
返回值:成功返回读到的字节,出错或者读到文件末尾时返回EOF

#include <stdio.h>

int fputc(int c, FILE *stream);
int putchar(int c);
返回值:成功返回写入的字节,出错返回EOF
  • 这两个函数都表示每次读取一个字节的数据,fgetc(stdin)和getchar的效果是一样的都是表示从终端读取。
  • 当读取文件结尾或者发生错误时返回FOF(-1),我们通常使用返回值和EOF比较来判断是否读取到结尾。
  • 在文件打开时FILE结构体中都有读写位置为0,因此我们可以使用这两个函数来进行多次读写,读写位置的偏移量加1。
  • 这两个函数的返回值都为整形,表示读取到的内容。
  • 下面是使用这几个函数的一个复制文件的例子
#include<stdio.h>
int main(int argc,char *argv[])
{
FILE *p=fopen("bb","r");
FILE *q=fopen("cc","w");
int c;
while((c=fgetc(p))!=EOF)
{
fputc(c,q);
}

fclose(q);
fclose(p);
}

文件的读写位置

我们使用函数来读写位置时,文件的读写位置也在变化,我们接下来介绍几个更改文件读写位置的函数。

#include <stdio.h>

int fseek(FILE *stream, long offset, int whence);
返回值:成功返回0,出错返回-1并设置errno

long ftell(FILE *stream);
返回值:成功返回当前读写位置,出错返回-1并设置errno

void rewind(FILE *stream);
  • fseek函数有三个参数,第一个参数表示文件的句柄,第二个参数表示文件的偏移量,第三个参数可以有三个选项。
  • 三个选项为:SEEK_SET表示从文件开头的偏移量,SEEK_CRU表示从当前的位置偏移offset,SEEK_END表示从文件的末尾的偏移量。
  • 偏移量offset可以正可负,负表示向前移几个单位,但是如果超过开始的位置便会报错,为正如果超过结尾的话便会将从结尾到最后的位置这中间的值设置为0。
  • ftell函数表示返回当前的读写位置。
  • rewind函数表示将读写位置设置为开始位置。
#include<stdio.h>
int main(int argc,char *argv[])
{
FILE *p=fopen("bb","r");
fseek(p,2,SEEK_SET);
printf("%ld",ftell(p));
fclose(p);
}

子字符串为单位的I/O操作

#include <stdio.h>

char *fgets(char *s, int size, FILE *stream);
char *gets(char *s);
返回值:成功时s指向哪返回的指针就指向哪,出错或者读到文件末尾时返回NULL

我们通常使用第一个函数不使用第二个函数,第二个函数比较危险,一般不使用,这个函数的作用是读取文件中的一行到s指向的缓冲区中。

  • 返回值为s指向的地址,如果出错或者读取完会返回NULL,因此我们通常使用这个来判断一个文件读取完。
  • 这个函数每次行读取一行,因此这个函数是以‘\n’来检查一行是否结束的。
  • 如果这行的长度大于指定的缓冲区的长度,在最后一个字符添加'\0',来表示结束,剩余的部分会在下次继续读取。
  • 需要注意的是换行符也是一个字符,会被读取。
fputs(const char *s,FILE *stream);
  • 这个函数表示向某个文件中输入s这个缓冲区的字符串。
  • 这个函数是以‘\0’标志结束的,和fgets不同的是以‘\n’结束的。
#include<stdio.h>
int main()
{

FILE *P=fopen("aaa","r");
char a[5];
fgets(a,5,P);
fputs(a,stdout);
}

这两个函数的总结:fgets函数在读取到表示读取一行文件,在遇到换行符时,会结束读取,表示读取一行结束,fputs函数表示向文件或终端中写入数据,这个函数是以‘\0’,来标志写入结束的。

相关文章

网友评论

      本文标题:标准I/O库

      本文链接:https://www.haomeiwen.com/subject/iubeqctx.html