IO进程(1)-- 标准IO

了解

IO:input/output,针对文件的输入输出。

Linux下的文件类型:

b (block块设备),

c (character字符设备),

d (directory目录),

- (普通文件),

l (link链接文件),

s (socket套接字文件),

p (pipe管道文件);


概念

C库中定义的一组用于输入输出函数

特点

1. 有缓冲机制,通过缓冲机制减少系统调用的次数,提高效率

2. 围绕进行操作,流用FILE *描述,FILE是一个保存文件信息的结构体

3. 默认打开了三个流,stdin(标准输入)、stdout(标准输出)、stderr(标准错误) ->结构体指针变量

缓存区

1.行缓存(和终端相关的)

刷新缓存的条件:

1) . 程序正常退出

2) . \n刷新缓存

3) . fflush强制刷新

4) . 缓存区满刷新

2.全缓存(和文件相关的)

刷新缓存的条件:

1) . 程序正常退出

2) . fflush强制刷新

3) . 缓存区满刷新

3.不缓存(没有缓存区,错误信息)


练习:计算标准输出行缓存区的大小

方法一:用循环打印数据的方法,计算出缓存区大小

#include 
int main(int argc, const char *argv[])
{
    int i;
    for (i = 0; i < 300; i++)
        printf("%4d",i);
    while(1);
    return 0;
}
IO进程(1)-- 标准IO_第1张图片

0-255,每个数字位宽占4位,共1024(1K)

方法二:用FILE结构体中成员计算缓存区大小

#include 
int main(int argc, const char *argv[])
{
    printf("hello"); //先使用一下缓冲区 不然打印为0
    printf(" %d\n",stdout->_IO_buf_end - stdout->_IO_buf_base);
    return 0;
}

函数

打开文件

FILE * fopen(const char *path, const char *mode);
功能:打开文件

参数:path:打开文件路径
     mode:打开方式:
        r:只读,流定位到文件开头
        r+:可读可写,流定位到文件开头
        w:只写,文件不存在->创建,文件存在->清空
        w+:可读可写,文件不存在->创建,文件存在->清空
        a:追加,文件不存在->创建,文件存在->追加,流定位到文件末尾
        a+:可读可写,文件不存在->创建,文件存在->追加,
            当第一次读文件流定位到开头,写文件定位到末尾

返回值:成功:文件流,FILE *
       失败:NULL,并设置errno

示例:

int main(int argc, char const *argv[])
{
    FILE *fp; 
    fp = fopen("./a.c","r+");  //在当前路径打开a.c文件,(可读可写权限)

    if(fp == NULL)
    {
        perror("open err\n");
        return -1;
    }
    printf("open suc\n");
    return 0;
}

读写文件

每次一个字符的读写

int fgetc(FILE *stream)
功能:从文件中读一个字符

参数:stream:文件流

返回值:
    成功:读到字符的ASCII码
    失败或读到文件末尾:EOF
-------------------------------
int fputc(int c, FILE * stream)
功能:向文件中写入一个字符

参数:c:要写的字符
   stream:文件流

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

练习:编程实现cat命令功能。

#include 
int main(int argc, char const *argv[])
{
    FILE *fp; //定义文件流
    fp = fopen("test.c","r");
    if(fp == NULL)
    {
        perror("open err\n");
        return -1; //非正常退出 -1
    }
    printf("open suc\n");
    int ch;
    // while((ch = fgetc(fp)) != EOF)
    // {
    //     printf("%c",ch);
    // }
    while(1) //也可以写成上述注释部分
    {
        ch = fgetc(fp);  //读取
        if (ch == EOF)   //失败或读到文件末尾返回EOF
            break;
        printf("%c",ch); //打印
    }
    return 0;
}
IO进程(1)-- 标准IO_第2张图片

每次一串字符的读写

char * fgets(char *s,  int size,  FILE * stream);
功能:从文件中每次读取一行字符串
参数:s:存放字符串的地址
     size:一次读取的字符个数
     stream:文件流
返回值:成功:s的地址
       失败或读到文件末尾:NULL
特性:每次实际读取的字符个数为size-1个,会在末尾自动添加\0
     遇到\n结束一次读
----------------------------------------------------
int  fputs(const char *s,  FILE * stream);
功能:向文件中写字符串
参数:s:要写的内容
     stream:文件流
返回值:成功:非负整数
       失败:EOF

练习:编程实现"wc -l 文件名"功能。通过fgets实现

计算文件的行数

#include 
#include 
int main(int argc, char const *argv[])
{
    FILE *fp;
    char buf[64] = "";
    fp = fopen(argv[1],"r+");  //可读可写权限
    if(fp == NULL)
    {
        perror("open err\n");
        return -1;
    }

    int i = 0;
    char *p = buf;
    while(fgets(buf,sizeof(buf),fp) != NULL)
    {
        if(buf[strlen(buf)-1] == '\n')
            i++;
    }
    printf("%d\n",i);
    return 0;
}

关闭文件

int fclose(FILE *stream);
参数:stream:文件流

编程实现head功能。

如:head -15 test.c -> ./a.out -15 test.c ->argv[1]:"-15"

#include 
#include 
#include 
int main(int argc, char const *argv[])
{
    FILE * fp;
    char buf[64] = " ";
    int i = 1,count = 0;
    if (argc != 3)
    {
        printf("usage:%s [-num] \n",argv[0]);
        return -1;
    }
    int num = abs(atoi(argv[1]));
    fp = fopen(argv[2],"r+");
    if (NULL == fp)
    {
        printf("打开失败\n");
        return -1;
    }

    while(fgets(buf,50,fp) != NULL)  //统计文件的行数
    {
        if(buf[strlen(buf)-1] == '\n')
            count++;
    }

    rewind(fp);
    while(i <= num && i <= count) //保证要显示的行数不多于文件的行数
    {
        fgets(buf, 64, fp);
        printf("%s",buf);
        i++;
    }
    fclose(fp);
    return 0;
}
IO进程(1)-- 标准IO_第3张图片

检测判断文件

int  feof(FILE * stream);
功能:判断文件有没有到结尾
返回:到达文件末尾,返回非零值
----------------------------
int ferror(FILE * stream);
功能:检测文件有没有出错
返回:文件出错,返回非零值

可如下判断:

    if(ferror(fp)) //判断读文件失败
        printf("error\n");
    if(feof(fp)) //判断读到末尾
        printf("eof\n");

二进制读写

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从文件流读取多个元素

参数:ptr :用来存放读取元素
     size :元素大小  sizeof(数据类型)
     nmemb :读取对象的个数
     stream :要读取的文件

返回值:成功:读取对象的个数
      读到文件尾: 0
       失败: -1
-----------------------------------------------------------------------
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:按对象写

参数:ptr :用来存放读取元素
     size :元素大小  sizeof(数据类型)
     nmemb :读取对象的个数
     stream :要读取的文件   

返回值:成功:写的元素个数
       失败 :-1

Fread和fwrite函数注意:
1)两个函数的返回值为:读或写的对象数
2)对于二进制数据我们更愿意一次读或写整个结构。

示例:

#include 
int main(int argc, char const *argv[])
{
    FILE *fp;
    int data[3] = {70, 80, 90};
    int array[3] = {100};
    fp = fopen("./test.c","r+");
    if(fp == NULL)
    {
        perror("open err\n");
        return -1; //非正常退出 -1
    }

    fwrite(array,sizeof(int),3,fp); //往fp文件流写入3个array里的int类型的数据
    rewind(fp); //定位至开头
    fread(data,sizeof(int),3,fp); //读出数据 被100 0 0覆盖
    for(int i = 0; i < 3; i++)
        printf("%d\n",data[i]);
    fclose(fp);    
    return 0;
}

重定向打开文件

FILE * freopen(const char *pathname,  const char *mode,  FILE* fp)
功能:将指定的文件流重定向到打开的文件中
参数:path:文件路径
mode:打开文件的方式(同fopen)
      fp:文件流指针
返回值:成功:返回文件流指针
      失败:NULL

示例:

#include 

int main(int argc, char const *argv[])
{
    printf("hello\n");

    //将标准输出重定向到打开的文件test.c中
    freopen("./test.c","r+",stdout);
    printf("world\n"); //即world重定向写入到test.c中

    //将标准输出重定向到终端文件
    freopen("/dev/tty","r+",stdout); ///dev/tty 当前的终端
    printf("nihao\n"); 
    return 0;
}
IO进程(1)-- 标准IO_第4张图片

文件定位操作

int fseek(FILE *stream, long offset, int whence);
功能:文件的定位操作
参数:stream:文件流
     offset:偏移量:正数表示向后文件尾部偏移,负数表示向文件开头偏移
     whence:相对位置:
           SEEK_SET:相对于文件开头
           SEEK_CUR:相对于文件当前位置
           SEEK_END:相对于文件末尾
返回值:成功:0
       失败:-1   

注:当打开文件的方式为a或a+时,fseek不起作用

long ftell(FILE *stream);
功能:获取当前的文件位置
参数:要检测的文件流
返回值:成功:当前的文件位置,出错:-1
fseek(fp, 0, SEEK_SET); ==>  rewind(fp);

示例:将test.c文件相对开头偏移10个字符,写入若干字符,计算当前指针所在位置

#include 
int main(int argc, char const *argv[])
{
    FILE *fp;
    fp = fopen("./test.c","r+");
    if(fp == NULL)
    {
        perror("open err\n");
        return -1; //非正常退出 -1
    }
    //将文件读写位置指针相对开头偏移10个字符
    fseek(fp,10,SEEK_SET);

    fputc('a',fp); //写入a字符
    fputs("hello",fp); //写入hello字符串

    //计算位置指针当前所在的位置
    long p = ftell(fp);
    printf("%ld\n",p);
   
    fclose(fp);    
    return 0;
} 

你可能感兴趣的:(嵌入式学习,IO进程,c语言,开发语言,ubuntu)