嵌入式Linux文件下I/O

本文详细介绍了标准I/O的工作原理,包括其定义、缓冲机制、流操作、文件打开方式(如fopen)、字符读写函数(如fgetc和fputc)以及如何使用这些函数实现基本文件操作和读写功能。特别关注了可移植性和流类型的缓冲处理。
摘要由CSDN通过智能技术生成

标准I/O

标准I/O由ANSI C标准定义

标准IO通过缓冲机制减少系统调用,实现更高效率

围绕流进行操作,默认打开三个流

在用户层,可移植性好

FILE   流   stream

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

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

一个FILE结构体就代表一个打开的文件

流的缓冲类型

全缓冲(文件相关)

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

行缓冲(终端相关

刷新标准输出缓存区的条件:

  • \n
  • 程序正常退出
  • 缓存区满
  • 强制刷新:fflush(NULL)

无缓冲(标准错误)

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

标准错误

打开流 打开文件 fopen

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

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

mode参数
r只读,当文件不存在时报错,文件流定位到文件开头,文件必须存在
r+

可读可写,当文件不存在时报错,文件流定位到文件开头,文件必须存在

w

只写,文件不存在创建,存在则清空

w+

可读可写,文件不存在创建,存在则清空

a

追加(在末尾写),文件不存在创建,存在追加,文件流定位到文件末尾

a+

读和追加,文件不存在创建,存在追加,读文件流定位到文件开头,写文件流定位到文件末尾

#include<stdio.h>

int main(int argc, char const *argv[])
{
    FILE *fp;
    if((fp=fopen("test.txt","w+"))==NULL);//关系运算符的优先级比赋值要高,需要加括号
    {
        perror("fopen err"); //如果以r方式打开,没有这个文件会报错,打印错误信息。
        return -1;
    }
    printf("fopen success\n");

    //2. 关闭文件
    fclose(fp);

    return 0;

}

 读写流

每次读写一个字符:fgetc()、fputc()

每次读一个字符fgetc()

int fgetc(FILE * stream);

功能:从文件中读取一个字符,并将当前文件指针位置向后移动一个字符。

参数:stream:文件流

返回值:成功:读到的字符

       失败或读到文件末尾:EOF(-1)

每次写一个字符fputc()

int fputc(int c, FILE * stream);

功能:向文件中写入一个字符, 成功写入后文件指针会自动向后移动一个字节位置。

参数:c:要写的字符

      stream:文件流

返回值:成功:写的字符的ASCII

       失败:EOF(-1)

getchar()等同于fgetc(stdin)

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

feof

int feof(FILE * stream);

功能:判断文件有没有到结尾,也就是当前所在位置后面还有没有字符。

返回:如果到达文件末尾,返回非零值。如果后面还有字符则返回0

#include <stdio.h>

int main(int argc, char const *argv[])
{
    FILE *fp;
    //1.打开文件
    fp = fopen("test.txt", "r+");
    if (NULL == fp)
    {
        perror("fopen err"); 
        return -1;
    }
    printf("fopen success\n");

    char ch = fgetc(fp);
    printf("%c %d\n", ch, ch);

    ch = fgetc(fp);
    printf("%c %d\n", ch, ch);

    if (feof(fp))
    {
        printf("end1\n"); 
        //不会打印出来,因为此时末尾还有一个EOF。
    }

    ch = fgetc(fp);
    printf("%c %d\n", ch, ch);

    if (feof(fp))
    {
        printf("end2\n");
        //会打印出来,因为此时已经到末尾了
    }

    //2. 关闭文件
    fclose(fp);

    return 0;
}

使用上述函数实现cat功能

#include <stdio.h>

int main(int argc, char const *argv[])
{
    char ch;
    if (argc != 2)
    {
        printf("format: %s <filename>\n", argv[0]);
        return -1;
    }

    //1.打开文件
    FILE *fp = fopen(argv[1], "r");
    if (NULL == fp)
    {
        perror("fopen err");
        return -1;
    }
    printf("open success\n");

    //2.循环用fgetc获取文件内容
    //3.当读到文件末尾EOF就结束
    // while ((ch = fgetc(fp)) != EOF)
    // {
    //     //4.将读到内容打印到终端
    //     fputc(ch, stdout);
    // }

    //或者
    while (1)
    {
        ch = fgetc(fp);
        if (feof(fp))
            break;
        fputc(ch, stdout);
    }

    //5.关闭文件

    return 0;
}

每次一串字符的读写 fgets() 和 fputs()

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

功能:从文件中每次读取一行字符串

参数:    s:存放字符串的地址

         size:期望一次读取的字符个数

         stream:文件流

返回值:成功:s的地址

       失败或读到文件末尾:NULL

特性:  每次实际读取的字符个数为size-1个,会在末尾自动添加\0

       每次读一行,遇到\n或者到达文件末尾后不再继续读下一行

       并把它存储在s所指向的字符串内。

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

功能:向文件中写字符串

参数:s:要写的内容

     stream:文件流

返回值:成功:非负整数

       失败:EOF

fgets() 和 fputs()对文件

#include<stdio.h>

int main(int argc, char const *argv[])
{
    char buf[100];
    FILE *fp;
    //打开文件
    if((fp=fopen("test.txt","r+"))==NULL)
    {
        perror("fopen err");
        return -1;
    }
    printf("fopen success\n");
    //读写
    fgets(buf,100,fp);
    fputs(buf,stdout);

    fgets(buf,100,fp);
    fputs(buf,stdout);

    fgets(buf,100,fp);
    fputs(buf,stdout);

    fclose(fp);
    return 0;
}
#include<stdio.h>
int main(int argc, char const *argv[])
{
    char buf[32]="55555";
    fgets(buf,32,stdin);
    printf("%s\n",buf);//

    fputs("man",stdout);
    printf("%s\n",buf);//
    return 0;
}
练习:通过fgets实现"wc -l 文件名"命令功能(计算文件行数)
#include <stdio.h>
#include <string.h>

int main(int argc, char const *argv[])
{
    int len = 0;
    char buf[32] = "";

    if (argc != 2)
    {
        printf("format: %s <filename>\n", argv[0]);
        return -1;
    }

    FILE *fp = fopen(argv[1], "r");
    if (NULL == fp)
    {
        perror("fopen err");
        return -1;
    }

    //循环读,读到末尾结束
    while (fgets(buf, 32, fp) != NULL)
    {
        //是否有换行,如果有就累加行数
        if (buf[strlen(buf) - 1] == '\n')
            len++;
    }

    printf("%d %s\n", len, argv[1]);
    //因为最后一行没有换行所以少一行,对标wc -l
    return 0;
}

总结

8个函数的总结
返回值举例
fopen
FILE  * fopen ( const char * path , const char * mode );

成功返回文件流

失败返回NULL

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

if (NULL == fp)

{

perror("fopen err"); //如果以r方式打开,没有这个文件会报错,打印错误信息。

return -1;

}

printf("fopen success\n");

fclose
int fclose ( FILE *  stream );
fclose ( fp );
fgetc
int fgetc ( FILE  *  stream );

成功返回读到的字符的ASCII

失败或者读到文件末尾返回EOF(-1)

//对文件读操作

char ch = fgetc(fp);

//对终端读操作

char ch = fgetc(stdin);

从文件中读取一个字符,并将当前文件指针位置向后移动一个字符

fputc

int fputc(int c, FILE * stream);

成功:写的字符的ASCII

失败:EOF(-1)

//向文件中写

fputc('a', fp);

fputc(98, fp);

//向终端中写

ch = fgetc(stdin)

fputc ( ch , stdout );
fgets
fgets
feof
ferror
fread
size_t fread ( void * ptr , size_t  size , size_t  nmemb ,  FILE  * stream );
fwrite
size_t fwrite ( const void * ptr , size_t  size , size_t  nmemb ,

              FILE *stream);

freopen
FILE  * freopen ( const char * pathname , const char * mode ,   FILE *  fp );

文件IO

标准IO与文件IO比较

标准IO与文件IO区别
标准IO文件IO
ANSICPOSTX
带缓冲无缓冲
流FILE文件描述符fd

什么是文件IO

1posix(可移植操作系统接口)定义的一组函数

不提供缓冲机制,每次读写操作都引起系统调用

核心概念是文件描述符

访问各种类型文件

LINUX下,标准IO基于文件IO实现

文件描述符

每一个打开的文件都对应一个文件描述符

非负整数,每次分配最小的可用的,从0开始依次递增

文件IO操作通过文件描述符完成

012

open

int open(const char *pathname, int flags);

功能:打开文件

参数:pathname:文件路径名

     flags:打开文件的方式

            O_RDONLY:只读

            O_WRONLY:只写

            O_RDWR:可读可写

            O_CREAT:不存在创建

            O_TRUNC:存在清空

            O_APPEND:追加   

返回值:成功:文件描述符

       失败:-1

例如:O_WRONLY|O_CREAT|O_TRUNC  ==> "w" 可写,不能存在时创建,存在则清空

当第二个参数中有O_CREAT选项时,需要给open函数传递第三个参数,指定创建文件的权限 

int open(const char *pathname, int flags, mode_t mode);

最后权限=创建出来的文件指定权限值&(~umask)

例如:指定权限为06668进制)

最终权限为0666&(~umask) = 0666&0775 = 0664

  • 22
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值