嵌入式开发学习--IO进程--标准IO、文件IO(含代码)

标准IO

什么是标准IO

概念
标准IO:是在C库中定义的一组专门用于输入输出的函数。
图片来源于网络,侵权立删
特点
(1)通过缓冲机制减少系统调用,提高效率。
系统调用:是内核向上提供的一组接口。
图片来源于网络,侵权立删
(2)围绕流进行操作,流用FILE *来描述
(3)标准IO默认打开三个流,stdin(标准输入) stdout(标准输出) stderr(标准错误)。

缓存区

(1)全缓存:和文件相关的
(2)行缓存:和终端相关的

刷新标准输出缓存区的条件:
●\n
●程序正常退出
●缓存区满
●强制刷新:fflush(NULL)
#include <stdio.h>

int main(int argc, char const *argv[])
{
    //printf("hello world\n"); //\n不光可以换行,还可以刷新标准输出的缓冲区
    printf("hello world");
    fflush(NULL); //强制刷新缓存区
    while (1);
    return 0;  //正常退出刷新刷存区
}

(3)不缓存:没有缓存,标准错误。
综上:当我们每次要打印数据时,并不是将数据直接发送给标准输出设备,也就是并直接发送给显示器,而是将要打印的数据先存放到缓存区,当缓冲存数据满时,或者遇到\n,或者程序结束时,或者手动刷新缓存区时,缓冲区才会把数据传输到标准输出设备中,也就是显示器中进行输出。
计算标准输出的缓存区大小 KB
方法一:利用循环打印展示
图片来源于网络,侵权立删
方法二:利用结构体指针stdout

#include <stdio.h>

int main(int argc, char const *argv[])
{
    printf("buf:"); //不进行输出的话缓存去不会开辟,所以需要开辟缓存区的话需要先调用标准输出函数。
    printf("%d\n",stdout->_IO_buf_end - stdout->_IO_buf_base);
    return 0;
}

函数接口

打开文件 fopen

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

参数:
    path:打开的文件路径
    mode:打开的方式
        r:只读,当文件不存在时报错,文件流定位到文件开头
        r+:可读可写,当文件不存在时报错,文件流定位到文件开头
        w:只写,文件不存在创建,存在则清空
        w+:可读可写,文件不存在创建,存在则清空
        a:追加(在末尾写),文件不存在创建,存在追加,文件流定位到文件末尾
        a+:读和追加,文件不存在创建,存在追加,读文件流定位到文件开头,写文件流定位到文件末尾
注:当a+的方式打开文件时,写只能在末尾进行追加,定位操作是无法改变写的位置,但是可以改变读的位置

返回值:
成功:文件流
失败:NULL,并且会设置错误码

关闭文件

int fclose(FILE* stream);
功能:关闭文件
参数:stream:文件流
#include <stdio.h>

int main(int argc, char const *argv[])
{
    FILE *fp;
    //1.打开文件
    //fp = fopen("test.txt","w");
    fp = fopen("test.txt", "r");
    if (NULL == fp)
    {
        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)

(1)针对文件

#include <stdio.h>

int main(int argc, char const *argv[])
{
    FILE *fp;
    //1.打开文件
    fp = fopen("test.txt", "r+");
    //fp = fopen("test.txt", "r");
    if (NULL == fp)
    {
        perror("fopen err"); //如果以r方式打开,没有这个文件会报错,打印错误信息。
        return -1;
    }
    printf("fopen success\n");

    //对文件读写操作
    char ch = fgetc(fp);
    printf("%c %d\n", ch, ch);//h 104

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

    fputc('a', fp);
    fputc(98, fp);

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

    return 0;
}

(2)针对终端

#include <stdio.h>

int main(int argc, char const *argv[])
{
    char ch = fgetc(stdin);
    //printf("%d %c\n", ch, ch);
    fputc(ch, stdout);

    ch = fgetc(stdin);
    //printf("%d %c\n", ch, ch);
    fputc(ch, stdout);

    return 0;
}

feof和ferror

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;
}
int ferror(FILE * stream);
功能:检测文件有没有出错
返回:文件出错,返回非零值。如果没有出错,返回0

例子;

#include <stdio.h>

int main(int argc, char const *argv[])
{
    FILE *fp;
    //1.打开文件
    fp = fopen("test.txt", "w");
    if (NULL == fp)
    {
        perror("fopen err"); 
        return -1;
    }
    printf("fopen success\n");
    char ch = fgetc(fp); //因为权限是只写,所以读操作有错误。
    if (ferror(fp))
    {
        printf("err!\n");
        return -1;
    }
    fclose(fp);
    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

(1)针对终端
图片来源于网络,侵权立删
(2)针对文件
图片来源于网络,侵权立删
二进制读写fread()和fwrite()

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从文件流读取多个元素(将二进制数据从文件读出)
参数:  ptr :是一个指针,是存放数据的存储空间的起始地址,用来存放读取元素
       size :元素大小  sizeof(元素数据类型)
       nmemb :读取元素的个数
       stream :要读取的文件流
返回值:成功:读取的元素的个数
       读到文件尾或失败: 0

size_t fwrite(const void *ptr, size_t size, size_t nmemb,
              FILE *stream);
功能:将二进制数据写入文件
参数: ptr :是一个指针,保存要输出数据的空间的地址。
     size :要写入的字节数 sizeof(数据类型)
     nmemb : 要进行写入元素的个数
      strem: 目标文件流指针
返回值:成功:写的元素个数
              失败 :-1

(1)针对终端

char buf[32]="";
    fread(buf,1,10,stdin);
    printf("%s\n",buf);
    fwrite(buf,1,10,stdout);

(2)针对文件

#include <stdio.h>

int main(int argc, char const *argv[])
{
    float arr[3] = {1.2, 3.4, 5.6};
    float data[3] = {};

    FILE *fp = fopen(argv[1], "r+");
    if (NULL == fp)
    {
        perror("fopen err");
        return -1;
    }
    fwrite(arr, sizeof(float), 3, fp);

    //定位操作
    rewind(fp); //将位置指针定位到文件开头,不然是接着上一步写的位置继续读的,由于是末尾所以读不到东西。

    fread(data, 4, 3, fp);

    printf("%f %f %f\n", data[0], data[1], data[2]);

    return 0;
}

文件定位到开头:rewind(fp);
图片来源于网络,侵权立删
重定向流到指定文件freopen

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

int main(int argc, char const *argv[])
{
    printf("hello\n");
    //将标准输出重定向到打开的test.txt中
    freopen("test.txt", "w+", stdout);
    printf("world\n");

    //将标准输出流重定向到终端文件/dev/tty
    freopen("/dev/tty", "r+", stdout);
    printf("66666\n");
    return 0;
}

文件定位操作

void rewind(FILE *stream);
功能:将文件位置指针定位到起始位置

int fseek(FILE *stream, long offset, int whence);
功能:文件的定位操作
参数:stream:文件流
     offset:偏移量:正数表示向后文件尾部偏移,负数表示向文件开头偏移
     whence:相对位置:
           SEEK_SET:相对于文件开头
           SEEK_CUR:相对于文件当前位置
           SEEK_END:相对于文件末尾
返回值:成功:0
       失败:-1 
注:当打开文件的方式为a或a+时,fseek不起作用    
补充:其中SEEK_SET,SEEK_CURSEEK_END和依次为012.
例子:
把fp指针移动到离文件开头100字节处:fseek(fp,100,0);
把fp指针移动到离文件当前位置100字节处:fseek(fp,100,1);
把fp指针退回到离文件结尾100字节处: fseek(fp,-100,2);

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

文件IO

什么是文件IO

概念
又称为系统IO,是系统调用,是操作系统提供的函数接口。posix中定义的一组用于输入输出的函数。POSIX接口 (英语:Portable Operating System Interface)可移植操作系统接口 。
图片来源于网络,侵权立删
特点
(1)没有缓冲机制,每次调用都会引起系统调用。
(2)围绕文件描述符进行操作,非负整数(>=0),依次分配
(3)文件IO默认打开了三个文件描述符,分别是0(标准输入)、1(标准输出)、2(标准错误)
(4)操作除了目录(d类型)文件的任意其他类型文件:b c - l s p
问题:打开三个文件,描述符分别是:3 4 5
关闭4以后,重新打开这个文件,文件描述符是几?
答:还是4
问题:一个进程的文件描述符最大到几?最多能打开多少个文件描述符?最多能打开多少个文件
答: 一个进程的文件描述符最大到1023(0-1023),最多能打开1024个文件描述符,最多能打开1024-3=1021个文件
操作
打开文件:open
关闭文件:close
读写操作:read、write
定位操作:lseek

函数接口

打开文件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

例子:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main(int argc, char const *argv[])
{
    int fd;
    //fd = open("./a.c", O_RDONLY);
    fd = open("./a.c",O_WRONLY|O_CREAT|O_TRUNC,0777);
    
    if (fd < 0)
    {
        perror("open err");
        return -1;
    }
    printf("fd:%d\n", fd);
    return 0;
}

文件IO和标准IO的打开方式的对应关系
图片来源于网络,侵权立删
关闭文件

int close(int fd);
功能:关闭文件
参数:fd:文件描述符

读写文件

读文件

ssize_t read(int fd, void *buf, size_t count);
功能:从一个已打开的可读文件中读取数据
参数: fd  文件描述符
      buf  存放位置
      count  期望的个数
返回值:成功:实际读到的个数(小于期望值说明实际没这么多)
       返回0:表示读到文件结尾
       返回-1:表示出错,并设置errno号

fgetc -> 失败和末尾:EOF
fgets ->失败和末尾:NULL
fread ->失败和末尾:0
read ->失败:-1 ;末尾:0
图片来源于网络,侵权立删
写文件

ssize_t write(int fd, const void *buf, size_t count);
功能:向指定文件描述符中,写入 count个字节的数据。
参数:fd   文件描述符
      buf   要写的内容
      count  期望写入字节数
返回值:成功:实际写入数据的个数
              失败  : -1
//返回值小于期望值是错误行为,可能磁盘满了无法再写。

文件定位操作

off_t lseek(int fd, off_t offset, int whence);
功能:设定文件的偏移位置
参数:fd:文件描述符
    offset: 偏移量  
        正数:向文件结尾位置移动
        负数:向文件开始位置
    whence: 相对位置
        SEEK_SET   开始位置
        SEEK_CUR   当前位置
        SEEK_END   结尾位置
补充:和fseek一样其中SEEK_SET,SEEK_CURSEEK_END和依次为012.

返回值:成功:文件的当前位置
        失败:-1
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{
    char buf[32] = "";
    int fd;
    fd = open("./a.c", O_RDWR);
    if (fd < 0)
    {
        perror("open err");
        return -1;
    }
    lseek(fd, 10, SEEK_END);
    write(fd, "k", 1);
    off_t off = lseek(fd, 0, SEEK_END);
    printf("%ld\n", off); //利用结尾偏移求出长度
    return 0;
}

标准IO和文件IO总结;
图片来源于网络,侵权立删

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值