Linux高级编程(一)标准io:stdio.h

标准io的概念

1975 Dennis r IO库,C语言的标准,ANSI c 
IO 即input  output
I: 键盘是标准输入设备 ====》默认输入就是指键盘  /dev/input
O: 显示器是标准输出设备 ==》默认输出就是指显示器
Linux操作系统当中IO都是对文件的操作
C一部分,任何支持标准C的系统都可使用标准IO实现文件存储
标准IO在UNIX上是对文件IO的封装

文件基本操作

文件操作步骤
1,打开文件  FILE 
2,io操作,,读写操作
3,关闭文件  

1, fopen

2, 读写操作相关, 
fgetc/fputc单个字符
fgets/fputs一次一行
fread/fwrite二进制的操作
3,fclose

fopen函数

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

1.功能:

打开一个文件并建立一个流

2.参数:

    path:要打开文件的路径
    mode:
        r    只读,文件不存在就报错;文件存在则只读打开

        r+    读写,文件不存在报错; 文件存在则读写打开

       w    只写,文件不存在则创建,文件存在则清0只写打开

       w+    写读,  文件不存在则创建;文件存在则清0写读打开

       a    追加可写,文件不存在则创建 ;文件存在则追加只写打开 ,定位到文件最后增加内容。

       a+    追加读写 ,文件不存在则创建  ;文件存在则追加读写打开


3.返回值:

    成功返回建立的文件流指针
    失败返回NULL  

使用:

#include <stdio.h>

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

    FILE * fp = fopen("1.txt","w");
    if(NULL == fp)
    {
        printf("fopen error\n");
        return 1;
    }
   // fputc();
   // fclose();
    return 0;
}

fputc

int fputc(int c, FILE *stream);

1.功能:

向流中写入一个字符   

2.参数:

    c:要写入的字符
    stream:文件流指针

3.返回值:

    成功返回写入的字符ASCII码值
    失败返回EOF

#include <stdio.h>

int main(int argc, char *argv[])
{
    FILE * fp = fopen("1.txt","w");
    if(NULL == fp)
    {
        printf("fopen error\n");
        return 1;
    }
    int ret = fputc('h',fp);
    if(-1 == ret)
    {
        printf("fputc error\n");
        return 1;
    }
    fputc('e',fp);
    fputc('l',fp);
    fputc('l',fp);
    fputc('o',fp);

    fclose(fp);
    return 0;
}

fgetc

int fgetc(FILE *stream);

1.功能:

    从流中读取一个字符

2.参数:

    stream:文件流指针

3.返回值:

    成功返回读到字符的ASCII码值
    读到文件末尾返回EOF
    失败返回EOF -1
    c= fgetc(stdin);
    fputc(c,stdout);
    获取键盘上面的输入,显示到屏幕

用法:

#include <stdio.h>

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

    FILE * fp = fopen("1.txt","r");
    if(NULL == fp)
    {
        printf("fopen error\n");
        return 1;
    }
    while(1)
    {
        int c = fgetc(fp);
        if(EOF == c)
        {
            break;
        }
        printf("%c\n",c);
    }
    fclose(fp);
    return 0;
}

fgets

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

1.功能:

从stream流对象关联的文件中获取size大小字节的文本数据,并存储到s对应的本地内存(栈区数组,堆区内存) 

2.参数:

       s 要存储数据的本地内存
       size 要获取的数据长度,单位字节。
       stream 要获取的目标文件流对象,
        可以是stdin ,程序会阻塞等待
        如果是普通文件fp 则指向文件第一行数据

3.返回值:

        成功 返回指向有效数据的首地址,一般等于s的地址
        失败 或者 文件末尾 NULL;

用法:

#include <stdio.h>
int main(int argc, char *argv[])
{

    FILE * fp = fopen("/etc/passwd","r");
    if(NULL == fp)
    {
        printf("fopen error\n");
        return 1;
    }
    char buf[1024]={0};// 1k-4k
    while(1)
    {
        char* s = fgets(buf,sizeof(buf),fp);
        if(NULL == s)
        {
            break;
        }
        printf("%s\n",buf);
    }
    fclose(fp);
    return 0;
}

fputs

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

1.功能:

从s所在的本地内存中获取一行数据,并写入stream对应的文件流对象。

2.参数:

       s 要写的信息,一般是固定的字符串或者有数据的数组。
       stream 要写入的目标文件流对象

3.返回值:

成功 nonnegative number on success
失败 -1;

用法:

#include <stdio.h>

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

    FILE * fp = fopen("1.txt","w");
    if(NULL == fp)
    {
        printf("fopen error\n");
        return 1;
    }
    char data[]="hello,world";
    int ret = fputs(data,fp);
    if(EOF == ret)
    {
        printf("fputs error\n");
        return 1;
    }
    fclose(fp);
    return 0;
}

fread和fwrite

fread

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

1.功能:

从指定的stream流对象中获取nmemeb个大小为size字节的数据块到ptr
      所在的本地内存中。
2.参数:

     ptr 要存储数据的本地内存一般是数组或者结构体指针
      size 单个数据块的元数据大小。最小单元的大小
      nmemb 要获取的数据块的个数,拷贝的数据块个数。
      stream 要获取数据的源文件流对象,如果是stdin表示从
      键盘获取数据,如果是fp文件则表示从普通文件获取。
3.返回值:

        成功 小于等于nemeb的整数,表示获取的数据长度
        失败 小于0,结尾 0;

fwrite

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

1.功能:

从ptr所在本地内存中取出nmemb个大小为size的数据块写入到stream流对应的文件流对象中。
     
2.参数:

    ptr 要写的数据块地址,一般是数组或者结构体指针
      size  要写的数据块元数据大小,单位是字节
      nmemb 要写的数据块的个数
      stream 要写的目标文件流对象。如果是stdout则表示数据会
      写到终端屏幕显示,如果是fp的普通文件则会写入到文件中。

3.返回值:

成功 小于等于nmemb 的个数。
失败 <0

用法:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct 
{
    char name[50];
    int age;
    char phone[15];
}PER;

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

    FILE * src_fp = fopen("/home/linux/1.png","r");
    FILE*  dst_fp = fopen("2.png","w");
    if(NULL == src_fp ||NULL == dst_fp)
    {
        printf("fopen error\n");
        return 1;
    }
    int size = 160743;// 1024*1024*1024
    char *p = (char* )malloc(size);// 32bit 2.9G   64bit 256T +256T
    fread(p,size,1,src_fp);
    fwrite(p,size,1,dst_fp);
    fclose(dst_fp);
    fclose(src_fp);
    free(p);
    return 0;
}

操作判断

ferror ():检测一个流是否出错

clearerr():void clearerr(FILE *stream); 清除一个流出错的标记

feof():检测是否到达文件结尾

feof() 函数判断

nt feof(FILE *stream);

1.功能:

判断当前参数stream的文件流指针是否到达文件结尾。
      如果到达文件结尾则返回真,否则返回假
      注意:该操作一定要在一次IO操作之后判断。

2.参数:

stream 要判断结尾的文件流对象

3.返回值:

成功到达结尾是 真
        否则 是假

用法:

if (feof(fp)) {
    printf("到达文件末尾!\n");
} else {
    printf("未到达文件末尾!\n");
}

if (ferror(fp)) {
    printf("出错!\n");
    clearerr(fp);
} else {
    printf("未出错!\n");
}

while(fgets(buf,1024,src))
{

}
//EOF 
	if(feof(src))
	{
		break;
	}
	if(ferror(src))
	{
		clearerr(src);
	}

文件定位:

fseek(重点)

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

1.功能:

将stream流文件中的文件指针从whence位置开始,偏移offset字节的长度。

offset偏移量,whence参考点。

2.参数:

stream  要移动文件指针的目标文件流对象。注意:不支持设备文件,一般用于普通文件。

offset  要在文件内偏移的距离,单位字节。如果值为正数,则向文件末尾偏移,如果值为负数,则向文件开头偏移。

whence  偏移的起始位置,由系统定义的三个宏
        SEEK_SET  文件的开头位置 
        SEEK_CUR  文件的当前位置
        SEEK_END  文件的末尾位置

3.返回值:    

    成功: 返回 0
    失败:  -1;

用法:

#include <stdio.h>

int main(int argc, char *argv[])
{
    
    FILE* fp = fopen("./01fopen.c","r");
    if(NULL == fp)
    {
        printf("fopen error\n");
        return 1;
    }

    int ret = fseek(fp,10,SEEK_SET);
    if(-1 == ret)
    {
        printf("fseek error\n");
        return 1;
    }

    char buf[512]={0};
    fgets(buf,sizeof(buf),fp);
    printf("buf is %s\n",buf);

    fclose(fp);


    return 0;
}

ftell

long ftell(FILE *stream);rewind(fp);

1.功能:

获取当前文件流指针的具体位置,一般以文件开头到当前指针的字节数为返回值。可以用来求文件大小

2.参数:

stream 要返回指针距离的文件流对象

3.返回值:

成功 返回获取到的距离长度,单位是字节;失败 返回-1    

用法:


#include <stdio.h>

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

    fseek(fp,0,SEEK_END);
    long size = ftell(fp);
    fclose(fp);
    printf("size is %ld\n",size);
    return 0;
}

rewind()

等效于:fseek(stream,0L,SEEK_SET);功能是回到文件开头

#include <stdio.h>

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

    FILE* fp = fopen("./01fopen.c","r");
    if(NULL == fp)
    {
        return 1;
    }

    fseek(fp,0,SEEK_END);
    long size = ftell(fp);
    printf("size is %ld\n",size);
    rewind(fp);
    char buf[512]={0};
    if(fgets(buf,sizeof(buf),fp))
    {
      printf("buf is %s\n",buf);  
    }
    else 
    {
        printf("end of file\n");
    }
    fclose(fp);
    return 0;
}

标准io缓冲区

要求掌握fflush函数

stdin标准输入

stdout标准输出

stderr标准错误输出,一般用在程序出现错误时。打印错误信息

行缓冲

1k, terminal,主要用于人机交互stdout。行缓存多是关于终端的一些操作

刷新条件:
1.遇到\n刷新
2.缓存区满刷新,缓存区满(1024个字节)
3.程序正常结束刷新
4.fflush函数刷新  fflush(stdout);

#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
 //不满足任意条件
    /* 1
    printf("hello");
    while(1)
    sleep(1);
    */ 

//缓存区满刷新
    /* 2
    int i=0;
    for(i=0;i<1025;i++)
    {
    
        //printf("a");
        fputc('a',stdout);//  stdin stdout stderr 
    }

    while(1)
    sleep(1);
    */ 
//程序结束刷新
/*3
    printf("hello");
    */ 

//fflush刷新
    printf("hello");
    fflush(stdout);
    while(1)
    sleep(1);
    return 0;
}

全缓冲

4k,主要用于文件的读写 ,对普通文件进行标准IO操作,建立的缓存一般为全缓存

刷新条件:
1.缓存区满刷新,缓存区满刷新,缓存区 4096
2.程序结束刷新,正常结束。
3.fflush来刷新  fflush(fp);

#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
// 不刷新
    /* 1
    printf("hello");
    while(1)
    sleep(1);
    */ 
//缓存区满刷新
    /* 2
    int i=0;
    for(i=0;i<1025;i++)
    {
    
        //printf("a");
        fputc('a',stdout);//  stdin stdout stderr 
    }

    while(1)
    sleep(1);
    */ 
//程序结束刷新
/*3
    printf("hello");
    */ 
//fflush刷新

    printf("hello");
    fflush(stdout);
    while(1)
    sleep(1);
    return 0;
}

无缓冲

0k  主要用于出错处理信息的输出 stderr 
    不对数据缓存直接刷新
    printf();==>>stdout 
    fprintf(strerr,"fopen error %s",filename);

 fprintf可以指定输出

两个重要的应用:

1.fputc/fgetc完成文件复制

#include <stdio.h>
//  ./a.out 4 5 56 7 8 
int main(int argc, char *argv[])
{

    if(argc<3)
    {
        printf("usage:./a.out srcfile dstfile\n");
        return 1;
    }
    FILE *src = fopen(argv[1],"r");
    FILE * dst= fopen(argv[2],"w");
    if(NULL == src || NULL == dst )
    {
        printf("fopen error\n");
        return 1;
    }
    while(1)
    {
        int c = fgetc(src);
        if(EOF== c)
        {
            break;
        }
        fputc(c,dst);
    }

    fclose(dst);
    fclose(src);
    return 0;
}

2.fputs/fgets完成文件复制

#include <stdio.h>

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

	if (argc < 3)
	{
		printf("usage ./a.out srcfile desfile\n");
		return 1;
	}
	FILE *src = fopen(argv[1],"r");
	FILE *dst = fopen(argv[2],"w");

	if (NULL == src || NULL == dst)
	{
		printf("fopen error\n");
		return 1;
	}
	char buf[1024] = {0};
	while (1)
	{
		char *s = fgets(buf,sizeof(buf),src);
		if (NULL == s)
			break;
		fputs(buf,dst);
	}
	fclose(dst);
	fclose(src);
	
	return 0;
}

  • 17
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值