Linux 标准I/O与文件I/O操作一篇就懂了

一、概述

  本文主要从介绍Linux 标准I/O操作以及文件I/O操作的主要区别以及使用方法,读完本文,即可以掌握两者之间的区别,也会使用他们在Linux 环境中编程,本文会列举介绍每种IO的接口API,并给出使用例程。

二、API介绍以及使用例程

2.1 什么是标准IO以及文件IO简介

文件I/O:文件I/O称之为不带缓存的IO(unbuffered I/O)。不带缓存指的是每个read,write都调用内核中的一个系统调用。也就是一般所说的低级I/O——操作系统提供的基本IO服务,与os绑定(特定于linix或unix平台)。

标准I/O:标准I/O是ANSI C建立的一个标准I/O模型,是一个标准函数包和stdio.h头文件中的定义,具有一定的可移植性。标准I/O库处理很多细节。例如缓存分配,以优化长度执行I/O等。标准的I/O提供了三种类型的缓存。

(1)全缓存:当填满标准I/O缓存后才进行实际的I/O操作。
(2)行缓存:当输入或输出中遇到新行符时,标准I/O库执行I/O操作。
(3)不带缓存:stderr就是了。

2.2 两种I/O的区别

  文件I/O 又称为低级磁盘I/O,遵循POSIX相关标准。任何兼容POSIX标准的操作系统上都支持文件I/O。
  标准I/O被称为高级磁盘I/O,遵循ANSI C相关标准。只要开发环境中有标准I/O库,标准I/O就可以使用。(Linux 中使用的是GLIBC,它是标准C库的超集。不仅包含ANSI C中定义的函数,还包括POSIX标准中定义的函数。因此,Linux 下既可以使用标准I/O,也可以使用文件I/O)。
  通过文件I/O读写文件时,每次操作都会执行相关系统调用。这样处理的好处是直接读写实际文件,坏处是频繁的系统调用会增加系统开销,标准I/O可以看成是在文件I/O的基础上封装了缓冲机制。先读写缓冲区,必要时再访问实际文件,从而减少了系统调用的次数。

  文件I/O中用文件描述符表现一个打开的文件,可以访问不同类型的文件如普通文件、设备文件和管道文件等。而标准I/O中用FILE(流)表示一个打开的文件,通常只用来访问普通文件。

2.3 什么是文件描述符

  Linux中的文件主要分为4种:普通文件、目录文件、链接文件和设备文件。这么的文件系统如何做区分呢?——文件描述符。文件描述符是个非负整数,是个索引值,并指向在内核中每个进程打开文件的记录表。在一个进程启动时,会自动打开3个文件:标准输入、标准输出和标准错误处理,这3个文件分别对应的文件描述符为0、1、2。

2.4 操作API的区别

项目标准I/O操作普通I/O 操作
打开fopen,freopen,fdopenopen
getc,fgetc,getchar,fgets,gets,freadread
putc,fputc,putchar,fputs,puts,fwritewrite
随机存取fseek、ftelllseek
关闭fcloseclose

三、标准I/O操作API使用总结

3.1 打开文件

  打开文件主要有几个API,fopen,freopen,fdopen。这里先简单介绍一下“文件”,“文件是指一组相关数据的有序集合”,这个数据集的名称就是文件名。所有文件都是通过流的形式进行输入输出操作的。流是一个数据字节的序列。流入程序的流称为输入流,流出程序的流称为输出流。
流可分为两大类:文本流和二进制流
(1)文本流是一种字符序列,仅包含字符。
(2)二进制流是一种二进制序列,与外设中的字节序列一一对应,不对字节中的内容进行转换,如遇到换行符也不会执行换行操作。
文本又可以分为文本文件和二进制文本文件两大类。
(1)文本文件又称ASCII文件,也称字符文件。这种文件保存时,每个字符对应一个字节,用于存放对应的ASCII码。可通过输出设备显示,是我们能够读懂的内容。
(2)二进制文件是由0和1组成的一段序列,用二进制的方式保存文件内容。虽然二进制也能够输出显示,但是只有机器能够读懂它的意思。
文件指针:

typedef struct
{
    short level;                /*缓冲区的使用量*/
    unsigned flags;             /*标志文件状态*/
    char fd;                    /*文件号*/
    unsigned char hold;         /* 无缓冲区取消字符输入*/
    short bsize;                /*缓冲区大小默认值512*/
    unsigned char *buffer;      /*缓冲区指针*/
    unsigned ar *curp;          /*无活动指针*/
    unsigned istemp;            /*草稿文件标识*/
    short token;                /*做正确性检测*/
}FILE;

fopen()函数是ANSIC规定的标准输入/输出函数库中的函数。打开文件的操作就是创建一个流。

#include <stdio.h>
FILE *fopen(const char *restrict pathname, const char *restrict type);
FILE *fropen(const char *restrict pathname, const char *restrict type, FILE *restrict fp);
FILE *fdopen(int filedes, const char *type);
返回值:成功返回文件指针,出错返回NULL

fopen打开一个指定的文件。
freopen在一个指定的流上打开一个指定的文件,如若该流已经打开,则先关闭流。若该流已经定向,则freopen清除该定向。此函数一般用于将一个指定的文件打开为一个预定义的流:标准输入、标准输出或标准出错。
fdopen获取一个现有的文件描述符,并使一个标准的I/O流与该描述符相结合。此函数常用于由创建管道和网络通信通道函数返回的描述符。因为这些特殊类型的文件不能用标准I/O fopen函数打开,所以必须先调用设备专用函数以获得一个文件描述符,然后用fdopen使一个标准I/O流与该描述符相关联。
fopen和freopen是ISO C的所属部分。而ISO C并不涉及文件描述符,所以仅有POSIX.1具有fdopen。

头文件: #include <stdio.h>
函数调用形式:fp = fopen("文件名","使用文件方式");
功能:以某种使用方式打开文件
返回值:若文件打开成功返回 一个有确定指向的FILE指针,打开失败则返回NULL。
使用方式含义

r 打开只读文件,该文件必须存在。
r+ 打开可读写的文件,该文件必须存在。
w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。
w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。
a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。
rb 打开一个二进制文件,只允许读数据
rb+ 打开一个二进制文件,允许读和写
wb打开或建立一个二进制文件,只允许写数据
wb+ 打开或建立一个二进制文件,允许读和写
ab 打开一个二进制文件,并在文件末尾写数据
ab+ 打开一个二进制文件,允许读,或在文件末追加数据
总结以上使用方式的特点:
①r(read)代表读,w(write)代表写,a(append)追加。
②r为打开只读文件,即文件存在才能读;w为打开只写文件,若文件不存在则建立,文件存在则先将文件内容清空再写数据;a为追加的方式写入数据,即文件不存在则建立,若文件存在,原文件内容不清空,并在末尾写入数据。
③b代表二进制的标识,意思是对二进制文件操作
④+代表可读和可写

3.2 读操作

int fgetc(FILE *stream);
int getc(FILE *stream);
char *fgets(char *s, int size, FILE *stream);
int getchar(void);
char *gets(char *s);

fgetc() 读取文件指针stream所指向文件的下一个字符,返回值是所读取字符强制类型转换成整数的值,如果到达文件尾部或者出错,则返回EOF。
getc()与fgetc()函数相同,只是它是一个宏实现。
getchar()等同于getc(stdin)从标准输入接收一个字符返回,多余的字符全部留在输入缓冲区,什么时候结束由程序员自己约定结束符,一般选择\n为结束符,当然也可以是任意其他字符。
gets()从标准输入读取一行到字符串指针s所指向的缓冲区,直到行结束(‘\n’)或遇到一个EOF,但不接收’\n’,把 ‘\n’留存输入缓冲区;把接收的一串字符存储在形式参数指针指向的空间,并在最后自动添加一个’\0’**
注意:该函数不检查缓冲区是否够大,是否有溢出。**
fgets()从文件指针stream所指向的文件中,最多取出size个字符存放到s所指向的换中去中。遇到EOF或一行结束时,读取停止,把’\n’也作为一个字符接收;。如果读取一行,它将该行存放到缓冲区,在最后一个字符的后边添加’\0’并放到缓冲区。
返回值:
fgetc(), getc() 和getchar()成功时返回读取字符的ASCII码值,失败时返回EOF。
gets() 和fgets() 成功时返回字符串的指针s,失败时返回NULL指针。
scanf遇到空格、回车和Tab键都会认为输入结束,所有它不能接收空格。

3.3 写操作

int putc( int c,FILE *stream);
int fputc(int c,FILE *stream);
int putchar(int c);
int fputs(const char *str, FILE *stream)int puts(const char *str);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)

① putc 把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动。
返回值:该函数以无符号 char 强制转换为 int 的形式返回写入的字符,如果发生错误则返回 EOF。
② fputc 把参数 char 指定的字符(一个无符号字符)写入到指定的流 stream 中,并把位置标识符往前移动。
返回值:如果没有发生错误,则返回被写入的字符。如果发生错误,则返回 EOF,并设置错误标识符。
③ putchar把参数 char 指定的字符(一个无符号字符)写入到标准输出 stdout 中。
返回值:该函数以无符号 char 强制转换为 int 的形式返回写入的字符,如果发生错误则返回 EOF。
f④ puts 把字符串写入到指定的流 stream 中,但不包括空字符。
返回值:该函数返回一个非负值,如果发生错误则返回 EOF。
puts 把一个字符串写入到标准输出 stdout,直到空字符,但不包括空字符。换行符会被追加到输出中
参数

fwrite 把 ptr 所指向的数组中的数据写入到给定流 stream 中。
ptr -- 这是指向要被写入的元素数组的指针。
size -- 这是要被写入的每个元素的大小,以字节为单位。
nmemb -- 这是元素的个数,每个元素的大小为 size 字节。
stream -- 这是指向 FILE 对象的指针,该 FILE 对象指定了一个输出流。

返回值
如果成功,该函数返回一个非负值,如果发生错误则返回 EOF。

3.4 随机存取

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

(1) fseek 设置流 stream 的文件位置为给定的偏移 offset,参数 offset 意味着从给定的 whence 位置查找的字节数。
参数:

stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
offset -- 这是相对 whence 的偏移量,以字节为单位。
whence -- 这是表示开始添加偏移 offset 的位置。它一般指定为下列常量之一
常量	描述
SEEK_SET	文件的开头
SEEK_CUR	文件指针的当前位置
SEEK_END	文件的末尾

返回值:如果成功,则该函数返回零,否则返回非零值。

(2) ftell 返回给定流 stream 的当前文件位置。
返回值:该函数返回位置标识符的当前值。如果发生错误,则返回 -1L,全局变量 errno 被设置为一个正值。
demo:

#include <stdio.h>

int main ()
{
   FILE *fp;
   int len;
   fp = fopen("file.txt", "r");
   if( fp == NULL ) 
   {
      perror ("打开文件错误");
      return(-1);
   }
   fseek(fp, 0, SEEK_END);
   len = ftell(fp);
   fclose(fp);
   printf("file.txt 的总大小 = %d 字节\n", len);
   return(0);
}

3.5 关闭

int fclose(FILE *stream)

fclose 关闭流 stream。刷新所有的缓冲区。
返回值:如果流成功关闭,则该方法返回零。如果失败,则返回 EOF。

四、文件I/O操作的使用API总结

4.1 打开文件

4.2 读文件

4.3 写文件

4.4 随机存取

4.5 关闭文件

未完…

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值