IO基础笔记

1.标准IO与文件IO的区别:

        1.标准IO是c库函数,文件IO是系统调用接口。

        2.标准IO自带缓存区,文件IO没有缓存。

        3.标准IO是文件IO基础上封装出来的API接口。

文件IO标准IO
缓存无缓存有缓存
高低级低级IO高级IO
操作对象文件描述符
能否打开设备文件可以不可以
指令open close read write sleekfopen fclose fread fwrite fseek

2.缓存区

        缓存区是内存空间的一部分,在内存内预留了一部分的存储空间。用来暂时保存输入输出等I/O操作的一些数据。这些预留的空间被称为缓存区。

        缓存区是为了减少cpu对磁盘的读取次数,从内存中读取数据来加快运行速度。

        1.全缓存:当缓存区满或者特定的情况下才会刷新。如对磁盘的读写。

        2.行缓存:当行缓存区中有换行符号\n就会刷新,如标准输入(stdin)输出流(stdout)。

        3.无缓存:任何东西进入立刻就会被刷新,例如标准错误流(stderr).

程序结束时三种缓存区都会刷新。

3.流

        在c语言中,将在不同的输入/输出设备之间进行传递的数据抽象为“流”。

        c语言中有三种标准流:标准输入流:stdin,标准输出流:stdout,标准错误流:stderr

        流在本质上是一个字节序列,输入函数的字节序列被称为输入流,输出函数的字节序列被称为输出流。

        根据数据的形式,输入输出流可以分为文本流和二进制流。

        文本文件:(又称为ASCII文件)该文件中一个字符占用一个字节,存储单元中存放单个字符对应的ASCII码,在文本文件中输入输出的数据是字符或者字符串,可以被修改。

        二进制文件:二进制文件是存储在内存的数据的映像,也称为映像文件,二进制流中输入输出的是一系列的二进制的0,1代码,不可以被修改。

4.文件

        C语言使用的文件系统:缓存文件系统(标准IO);非缓存文件系统(系统IO)

        文件指针:在c语言中,所以的文件都必须依靠指针完成,通常用fopen()为文件变量进行赋值

        FILE *变量名

5.文件描述符

        文件描述符:是内核为了高效的管理已被打开的文件的所创建的索引,是一个非负的整数(通常为0~1023),所有的执行IO操作的系统调用都是通过文件描述符实现的。规定文件系统刚启动是:0是标准输入,1是标准输出,2是标准错误。所有打开一个新文件时它的文件描述符从3开始。

        简单来说,文件描述符就是一个下标,下标的内容指向打开的文件的指针。

关于文件描述符,linux内核维护了三个数据结构:

        1.进程级的文件描述符表。

                一个进程启动后,会在内核空间创建一个PCB控制块(PCB为进程控制块的缩写,包含包括进程状态,程序计数器,堆栈指针,打开文件列表,进程优先级等,用于在进程切换时对该进程的PCB进行保存与恢复)

        2.系统级的打开文件描述表

                ·当前文件的偏移量

                ·打开文件时的标识(open()函数里的参数)

                ·文件的访问模式

                ·信号驱动的相关配置

                ·对该文件i-node对象的引用,即i-node指针

        3.文件系统的i-node表

                ·文件的类型(如常规文件,套接字或者FIFO)和访问权限

                ·一个指针,指向该文件所持有的锁链表(对文件的锁定)

                ·文件的各种属性,包括文件的大小以及不同类型操作相关的时间戳

6.IO函数

        改变缓存区类型:setvbuf

int setvbuf(FILE *stream,char *buf,int mod,size_t size)
stream:流,表示目标文件的流
buf:缓存区地址,NULL表示系统默认的缓存区地址
mode:表示缓存区的类型
        _IONBF:无缓存
        _IOLBF:行缓存
        _IOFBF:全缓存
size:要更改的buf的大小,BUFSIZ表示系统默认的缓存区大小
功能:改变指定的缓存区的类型
返回值:成功返回0,失败返回非0

        出错提醒:perror errno stderr

perror:直接输出错误信息
error:输出错误号,用于内核调用完函数后设置调用结果的编号,int类型
stderr:标准错误流

        强制刷新缓存区:fflush

int fflush(FILE *stream)
功能:强制刷新缓存区
返回值:成功返回0,失败返回非0

        打开一个文件/流:open  fopen

int open(const char *pathname,int flages);
int open(const char *pathname,int flages,mode_t mode);
返回值:成功返回文件描述符,失败返回-1
pathname:文件路径,包含文件名
flages:文件打开/创建模式(必选)
        O_RDONLY (只读)
        O_WRONLY(只写)
        O_RDWR  (读写)
    下列为辅助选项,中间用|连接    如(O_WRONLY|O_APPEND)
        O_CREAT:如果文件不存在则创建一个新的文件,并用第三个参数表示其权限
        O_EXCL:如果使用O_CREAT时文件已经存在,则返回错误信息,这一参数可以测试文件是否存在
        O_NOCTTY:使用本参数时,若文件为终端,则终端不可以调用open()系统调用的那个进程的控制终端
        O_APPEND:表示以追加的方式打开文件,所以对文件的写操作都在文件的末尾进行
        O_TRUNC:若文件已经存在,则打开时先删除文件中的内容
mode:指定文件的访问权限,是由(-rw-r--r--)之类的组成的参数(0644)最高的权限为(777)

FILE *fopen(const char *pathname,const char *mode);
功能:让内核打开一个文件并标记
返回值:成功返回流指针,失败返回NULL
pathname:文件路径,包含文件名
mode:文件打开方式
        “r”只读的方式打开文件,文件必须存在
        “w”只写的方式打开文件,文件存在这清空,不存在则创建
        “a”以追加的方式打开文件,文件不存在则创建文件
        “r+”读写的方式打开文件,文件必须存在
        “w+”读写方式打开文件,文件存在这清空文件,不存在则创建文件
        “a+”读写方式打开,文件不存则创建文件,在文件末尾添加数据(追加时是在文件的末尾另起一行添加,想要在末尾添加需要使用fseek偏移后用fputs)

如果时操作二进制文件,在打开文件时可以加上b(如r+b,wb等),Linux不区分二进制流和文本流

                                    open和fopen的区别
open()和fopen都是用于打开文件的函数,他们的区别主要有:
1.语法不同:open()是一个系统调用,使用C语言函数语法,fopen是一个标准C库函数,使用C库标准语法
2.返回值不同:open()返回值是一个文件描述符,而fopen()的返回值是一个文件指针
3.文件模式不同:open()可以打开任何类型的文件,包括设备文件和管道等,而fopen()只能打开普通文件。另外open可以指定文件的打开模式,如只读,只写。读写等。而fopen()只能指定文件的访问模式,如只读,只写,读写等
4.缓存不同:fopen()会创建一个缓存区,用于提高读写的速率,而open不会创建缓存区
5.如果需要打开普通文件并使用标准的C库函数进行读写操作,应该使用fopen()函数;如果需要打开设备文件,管道文件等非普通的文件。使用使用open()函数。

 关闭一个文件/流:close fclose

关闭文件/流:close和fclose

int close(int fd)
功能:改变文件描述符,但不删除文件(删除用unlink())
返回值:成功返回0,失败返回EOF
fd:文件描述符

int fclose(FILE *fd)
功能:关闭yijing打开的流,防止损坏
返回值:成功返回0,失败返回EOF

close与fclose的区别;
1.关闭文件不同:close关闭open打开的文件,fclose关闭fopen打开的文件
2.缓存不同:close不会刷新缓存区,但是fclose会刷新缓存区

文件/流的偏移:lseek和fseek

off_t lseek(int fd,off_t offset,int whence)
功能:用于在用于在打开的文件描述符中设置文件偏移量,文件偏移量是文件    中下一个读取或者写入的操作的位置
返回值:成功返回off_t整形新的文件偏移量,失败返回-1
fd:文件描述符
whence:基准位置 可以取下面的值
    SEEK_SET: 基准位置为从文件开头
    SEEK_CUR;基准位置为当前位置
    SEEK_END;基准位置为从文件结尾


int fssek(FILE *stream,long offset,int whence)
功能:用于设置文件指针的位置
返回值:成功返回0,失败返回非0
stream:指向要设置位置的文件的指针
offset:要设置的相对位置
whennce;指向相对位置的起始点,可以从以下选择
    SEEK_SET: 基准位置为从文件开头
    SEEK_CUR;基准位置为当前位置
    SEEK_END;基准位置为从文件结尾  


lseek与fseek间的区别
1.操作文件不同:lseek操作open打开的文件流,fseek操作fopen打开的文件描述符
2.缓存不同:lseek不会刷新缓存,fssek会刷新缓存

        读写文件/流        
按字符读:getc,fgetc

int getc(FILE *fd)
功能:从文件内读取一个字符
返回值:成功返回读到的值,失败返回EOF


int fgetc(FILE *fd)
功能:从流里面读取一个字符
返回值;成功返回读到的字符,失败返回EOF

两者的功能等价,但是getc()函数的的参数可以是任意的文件指针,包括标准输入输出,错误流或者是文件描述符。fgetc()的参数必须是一个指向文件的指针

按字符写:putc fputc 

int putc(int c,FILE *fd)
功能:往文件内写入一个字符
返回值:成功返回写入的字符,失败返回EOF
c:要写入的字符

int fputc(int c,FILE *fd)
功能;往流内写入一个字符
返回值:成功返回写入的字符,失败返回EOF


两者完全等价,参数都可以填文件指针或者文件描述符

按行读:gets,fgets

gets函数可能会导致缓存区溢出,不建议使用

char *fgets(char *s,int size,FILE *fd)
功能:读取一行的内容
返回值:成功返回s的地址,失败返回NULL
s:要把内容读到哪里去(缓存区)
size:预计要读的字节数,一般用sizeof()
fd:从哪个流读取

fgets是表示遇到换行符才终止并且把换行符存进去,如果size比一行的数据大就读完所有内容,size如果比一行数据小只读取size-1个,在最后追加一个'\0'表示没有读完(表示后面一定会加'\0',在遇到文件末尾时才会加'\n',再加'\0'。可以利用'\0'前面是否有'\n'来判断这一行是否读完)

sizeof计算的是有效长度,
例如:sizeof(str)表示str的有效长度,即整个长度-1,假设char str[6],那么sizeof(str)为5

按行写:puts fputs

int puts(const char *str)
功能:将一个字符串输出到标准输出流
返回值:成功返回非负数,失败返回EOF
str:一个字符串
注:puts函数在调用时会自动添加换行符,如果要输出多个字符串需要多次的调用,不需要自动换行时需要在在文末添加 \ 来取消换行功能
例:puts("hello world \\");

int fputs(const char,FILE *fd)
功能:往一个流里面写一行数据
返回值:成功返回非负数,失败返回EOF
char:表示要写入的内容所在的缓存区,
fd:要写入的流
注:fputs不会自动换行

按对象读 read fread

size_t reaad(int fd,void *fd,size_t count)
功能:从文件描述符中读取数据的系统调用
返回值:成功返回读取到的字节数,如果读取到末尾返回0,失败返回EOF
fd:文件描述符
buf:要存放读取数据的缓存区
count:要读取的数据


size_t fread(void *ptr,size_t size,size_t nmemd,FILE *stream)
功能:从流里读取数据,内容分组
返回值:成功返回读取到的对象个数,失败返回EOF
ptr:要把读取的内容放在哪个缓存区
size:每个对象的字节大小
nmemb:预计要读的对象个数
stream:要读的流


注:预计要读的对象数nmemb不能超过缓存区(ptr)的大小

read和fread的区别
read函数是系统调用,直接与操作系统交互,因此他的效率比fread高。但是,fread是标准库函数,具有更好的可移植性。在读取文本时,fread函数会自动进行字符集转换,而read函数不会。
所有要是高效的读取二进制文件,可以使用read函数;要是读取文本文件或者需要移植性更好的代码需要使用fread函数。

按对象读:write fwrite

size_t write(int fd,const void *buf,size_t count)
功能:将数据将指定的文件缓存区写入文件描述符中
返回值:成功返回写入的字节数,失败返回EOF
fd:文件描述符
buf:要写入的数据的缓存区
count:要写入的字节数


size_t fwrite(const void *ptr,size_t size,size_t nmemb,FILE *stream)
功能:将缓存区的内容写入流
返回值:成功返回写入的对象个数,失败返回EOF
ptr:要写入数据所在的缓存区
size:每个对象的字节大小
nmemb:预计要写入的对象个数
stream:要写入的流

write函数和fwrite的区别:
write是系统函数,直接将数据写入文件内.write函数需要的参数是文件描述符,返回值是实际写入的字节数
fwrite是标准库函数,先将数据写入缓存区内再调用库函数将缓存区内的数据写入文件内。函数需要参数是文件流,返回值是实际写入的数据项个数

重定向

FILE *freopen(const char *pathname,const char *mode,FILE *stream)
功能:打开一个文件并产生一个流,stream所表示的流会被代替
返回值:成功返回流指针,失败返回NULL
pathname:要打开的文件
mode:打开的方式,如“w”等
stream:要重定向的流

例:
#include <stdio.h>

int main()
{
    FILE *fp;
    fp = fopen("output.txt","w",stdout);
    printf("This will be write to output.txt\n");
    fclose(fp);
    return 0;
}

在本例中,freopen函数将stdout流指向output.txt文本文件,打开方式为写,我们在使用printf函数向stdout写入一条信息,这条信息会被输入到文件output.txt中,我们查看文件就可以看见我们的打印信息。最后我们关闭文件指针fd,程序结束

注:freopen函数只能用于重定向标准的输入输出流,不能用于其他的类型的流

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值