标准IO

文件类型:

       常规文件 r

       目录文件 d

       字符设备文件 c

       块设备文件 b

       管道文件 p

       套接字文件 s

       符号链接文件 I

标准IO  流

       FILE:

              标准IO用一个结构体类型来存放打开的文件的相关信息

              标准IO的所有操作都是围绕FILE进行的

       流:

              FILE又被称为流

              文本流/二进制流

文本流和二进制流:

       Windows:

              二进制流:换行符 ---- ‘\n’

              文本流:  换行符 ---- ‘\r’’\n’

       Linux:

              换行符 ---- ‘\n’

流的缓冲类型:

       全缓冲:

              当流的缓冲区无数据或无空间时才执行实际IO操作

       行缓冲:

              当在输入和输出中遇到换行符 ‘\n’ 时,进行IO操作

              当流和一份终端关联时,典型的行缓冲

       无缓冲:

              数据直接写入文件,流不进行缓冲

标准IO定义三个流,程序运行时自动打开:

       标准输入流                  0                   STDIN_FILENO                    stdin

标准输出流                  1                   STDOUT_FILENO                 stdout

标准错误流                  2                   STDERR_FILENO                  stderr

-------------------------------------------------------------------------------

打开一个标准IO流:

FILE *fopen(const char *path,const char *mode);

 

成功时返回流指针,出错返回NULL

 

mode参数

r 或 rb

以只读方式打开文件,文件必须存在

r+ 或 r+b

以读写方式打开文件,文件必须存在

w 或 wb

以只写方式打开文件,若文件存在,则文件长度清0.若文件不存在,则创建文件。

w+ 或 w+b

以读写方式打开文件,其他同 w

a 或 ab

以只写方式打开文件,若文件不存在,则创建;向文件写入的数据被追加在文件末尾。

a+ 或 a+b

以读写方式打开文件,其他同 a

当给定“b”参数时,表示以二进制方式打开文件,但Linux下忽略该参数

 

fopen() 创建的文件访问权限是0666(rw-rw-rw-)

Linux系统中umask设定会影响文件的访问权限,规则为(0666&—umask)

用户可通过umask函数修改相关设定

 

fopen示例:

#include <stdio.h>

 

int main(int argc,char *argv[])

{

      

       FILE *fp;

       if((fp = fopen("fopendemo.txt","r+")) == NULL)

       {

              printf("fopen error\n");

              return -1;

       }

       return 0;

}

 

-------------------------------------------------------------------------------

处理错误信息

extern int errnor;           存放错误号

void perror(const char *s);   先输出字符串s 再输出错误号对应的错误信息

char *sterror(int errno);      根据错误号返回对应错误信息

 

示例:

#include <stdio.h>

#include <string.h>

#include <errno.h>

 

int main(int argc,char *argv[])

{

 

       FILE *fp;

       if((fp = fopen("test.txt","r+")) == NULL)

       {

 

              printf("fopen : %s \n",strerror(errno)); 

              return -1;

       }     

       return 0;

} return 0;

 }

输出结果

-------------------------------------------------------------------------------

关闭流

int fclose(FILE *stream);

 

调用成功返回0,失败返回EOF,并设置errno

流关闭时自动刷新缓冲中的数据并释放缓冲区

当一个程序正常终止时,所有打开的流都会被关闭

流一旦关闭后就不能执行任何操作

-------------------------------------------------------------------------------

读写流

读写一个字符:(一般读写二进制文件)

fgetc() / fputc() 一次读/写一个字符

 

读写一行:(一般读写文本文件,读取文本时,0会与 \0 冲突)

fgets() / fputs() 一次读/写一行

 

读写若干个对象:(可读写二进制文件,也可读写文本文件,效率高,推荐)

fread() / fwrite() 每次读/写若干个对象,而每个对象具有相同的长度

 

1.按字符输入输出

1.1按字符输入

int fgetc(FILE *stream);

int getc(FILE *stream);

int getchar(void);

 

成功时返回读取到的字符,若到文件末尾或出错返回EOF

getchar() 等同于 fgetc(stdin)

 

示例:统计文件大小

#include <stdio.h>

#include <string.h>

#include <errno.h>

int main(int argc,char *argv[])

{

 

       FILE *fp;

       int ch,count = 0;

      

       if((fp = fopen(argv[1],"r")) == NULL){

              perror("fopen");

              return -1;

       }     

 

       while((ch = fgetc(fp)) != EOF){

              count++;

       }

       printf("total %d bytes\n",count);

}

 

1.2按字符输出

int fputc(int c,FILE *stream);

int putc(int c,FILE *stream);

int putchar(int c);

参数c 输出的字符

参数 stram 选择输出的流

成功时返回写入的字符;出错时返回EOF

putchar(c) 等同于 fputc(c,stdout)

示例:向一个打开的文件写入26个英文字母

#include <stdio.h>

#include <string.h>

#include <errno.h>

int main(int argc,char *argv[])

{

 

       FILE *fp;

       int ch;

 

       if((fp = fopen(argv[1],"w")) == NULL){

      

              perror("fopen");

              return -1;

       }

      

       for(ch = 'a';ch <= 'z';ch++){

 

       fputc(ch,fp);

       }

}

 

示例:把一个文件内容写到另一个文件(argv[1]源文件,argv[2]目标文件)

#include <stdio.h>

#include <string.h>

#include <errno.h>

int main(int argc,char *argv[])

{

 

       FILE *fps,*fpd;

       int ch;

      

       if(argc < 3)

       {

 

              printf("Usage: %s <src_file> <dst_file>\n",argv[0]);

              return -1;

       }     

 

       if((fps = fopen(argv[1],"r")) == NULL)

       {

              perror("fopen src file");

              return -1;

       }

 

 

       if((fpd = fopen(argv[2],"w")) == NULL)

       {

              perror("fopen dst file");

              return -1;

       }

 

       while ((ch = fgetc(fps)) != EOF)

       {

              fputc(ch,fpd);

       }

       fclose(fps);

       fclose(fpd);

}

diff 比较文本文件

若有不一样的地方,会输出不一样的内容

 

2 按行输入输出

2.1按行输入

char *gets(char *s);

char *fgets(char *s,int size,FILE *stream);    从指定的流读取指定大小的字符放入缓冲区中

 

成功时返回s,到文本末尾或出错时返回NULL

gets 不推荐使用,容易造成缓冲区溢出

遇到‘\n’或已输入size-1个字符时返回,总是包含‘\0’

 

*s 缓冲区首地址

*stream 流指针

size 大小

 

gets()

没有定义缓冲区大小

如果用户输入 字符大小 超过缓冲区大小 会造成缓冲区溢出

fgets相对于gets更安全

 

size-1 原因

应为还要在读取到的字符串末尾加上 ‘\0’

 

示例:

#include <stdio.h>

#include <string.h>

#define N 6

 

int main()

{

       char buf[N];

 

       fgets(buf,N,stdin);

       printf("%s",buf);

       return 0;

}

2.2按行输出

int puts(const char *s);

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

 

成功时返回输出的字符个数,出错返回EOF

puts将缓冲区s中的字符串输出到stdout,并追加'\n'

fputs将缓冲区s中的字符串输出到stream

 

#include <stdio.h>

#include <string.h>

#include <errno.h>

 

int main(int argc,char *argv[])

{

 

       FILE *fp;

       char buf[] = "hello world";

       if((fp = fopen(argv[1],"a")) == NULL)

       {

              perror("fopen");

              return -1;

       }

       fputs(buf,fp);

       return 0;

}

 

按指定对象输入输出

size_t fread(void *ptr,size_t size,size_t n,FILE *fp);

 

size_t fwrite(const void *ptr,size_t size,size_t n,FILE *fp);

 

成功返回读写个数;出错返回EOF

既可读写文本文件,也可读写数据文件

 

size_t fread()

void *ptr 缓冲区首地址

size_t size 指定这次从流中读取的每个对象所占的大小

size_t n 指定从流中读取多少个对象

FILE *fp 流指针 用来选择从那个流中读取数据

 

示例:实现文件的复制

#include <stdio.h>

 

#define N 64

 

int main(int argc,char *argv[])

{

       FILE *fps,*fpd;

       char buf[N];

       int n;

 

       if(argc < 3)

       {

 

              printf("Usage : %s <src_file> <dst_file> \n",argv[0]);

              return -1;

       }

       if((fps = fopen(argv[1],"r")) == NULL)

       {

              perror("fopen src file");

              return -1;

       }

       if((fpd = fopen(argv[2],"w")) == NULL)

       {

              perror("fopen dst file");

              return -1;

       }

       while((n = fread(buf,1,N,fps)) > 0)

       {

 

              fwrite(buf,1,n,fpd);

       }

       fclose(fps);

       fclose(fpd);

}

刷新流

流自动刷新缓冲区

  1. 缓冲区满或者出现换行符‘\n’
  2. 关闭流时
  3. Fflush()函数刷新

 

int fflush(FILE *fp);

成功返回0,出错返回EOF

将流缓冲区中的数据写入实际文件

Linux下只能刷新出缓冲区

 

#include <stdio.h>

 

int main()

{

 

       FILE *fp;

       if((fp = fopen("test.txt","w")) == NULL)

       {

              perror("fpeon");

              return -1;

       }

       fputc('a',fp);

       fflush(fp);

       while(1);

       return 0;

}

定位流

long ftell(FILE *stream);

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

void rewind(FILE *stream);

 

ftell() 成功时返回当前读写位置,出错返回EOF

fseek() 定位一个流,成功时返回0,失败返回EOF

whence参数:基准点

              SEEK_SET 文件开始位置

SEEK_CUR 文件当前读写位置

SEEK_END 文件末尾

offset 偏移量,可正可负

0 文件开始位置

 

流的读写位置 = 偏移量 + 基准点

 

rewind() 将流定位到文件开始位置

读写流时,当前读写位置自动后移,不需程序控制

 

示例

在文件末尾添加字符

 

#include <stdio.h>

 

void main()

{

 

       FILE *fp = fopen("test.txt","r+");

       fseek(fp,0,SEEK_END);

       fputc('t',fp);

}

获取文件长度

#include <stdio.h>

 

int main()

{

 

       FILE *fp;

       if((fp = fopen("test.txt","r+")) == NULL)

       {

              perror("fopen");

              return -1;

       }

 

       fseek(fp,0,SEEK_END);

       printf("length is %ld \n",ftell(fp)); 

return 0;

 

}

判断流是否出错和结束

int ferror(FILE *stream);

       返回1表示出错,否则返回0

int feof(FILE *stream);

       返回1表示到末尾,否则返回0

 

格式化输出

int printf(const char *fmt,…);

int fprintf(FILE *stream,const char *fmt,…);        输出到流stream中

int sprint(char *s,const char *fmt,…);                 输出到缓冲区中

成功时返回字符个数,失败时返回EOF

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

点灯师

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

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

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

打赏作者

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

抵扣说明:

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

余额充值