嵌入式学习(标准IO)

linux应用编程 (高级编程)
IO
多任务
网络

IO(文件) 

文件操作:
文本文件,mp3,jpeg,png ,mp4,avi

文件:
    一组相关数据的有序集合
文件名:
    这组相关数据的一个名称

linux里面对文件的处理:
思想:
      一切皆文件 ,文件用来存储数据(数据、指令)
      everything is file!
      

b c d - l p s 

b -- block      -- 块设备文件   --- 硬盘(存储设备) 
c -- character  -- 字符设备文件 --- 鼠标 (输入输出设备)
d -- directory  -- 目录文件     
- -- regular    -- 普通文件 (分类:二进制文件:.jpg  .bmp  .mp4  a.out
                        ASCLL文件: .txt  .c  .h)
l -- link       -- 软连接文件   --- 类似windows的快捷方式  
p -- pipe       -- 管道文件     --- 实现操作系统中 进程间的一些 信息交换(通信)
s -- socket     -- 套接字文件   --- 网络的时候 (进程间的通信)


【操作文件的基本思路及框架】//凡是文件,都可从这个思路出发进行思考
文件操作三步骤:
1.打开 
2.读写    
3.关闭 

Linux提供的两种文件操作方式:
文件编程:
1.标准IO --- 库函数  -------标准c库函数,
2.文件IO --- 系统调用-------Linux内核为用户提供的函数接口


系统调用:Linux内核为用户提供的函数接口
库函数:标准c库函数, 对Linux内核中系统调用的封装
    
    

标准IO库:
1.标准io的概念 
    1975 Dennis Ritchie编写, IO库,
    从C语言的标准,ANSI c 
    IO  input  output
    I: 键盘是标准输入设备 ====》默认输入就是指键盘  /dev/input
    O: 显示器是标准输出设备 ==》默认输出就是指显示器
    
    Linux操作系统当中IO都是对文件的操作
    C一部分,任何支持标准C的系统都可使用标准IO实现文件存储
    标准IO在UNIX上是对文件IO的封装
   
    一般都是对普通文件操作是一种有缓存的IO 在文件IO和用户程序之间,
    加入缓冲区,可以有效减少系统调用的次数,节省系统IO调度资源
    


2.功能:
  用来操作普通文件
      普通文件:
        1.ASCII码文件(代码、文本文件)
        2.二进制文件(音视频、图片)
        
        ASCII码文件是一种特殊的二进制文件
        
        2021
        '2' '0' 2' '1' 
        
        2021
        0000 0000 0000 0000 0000 0111 1110 0101


3.操作方法
    1.打开 -- fopen  //FILE open
    2.读写 --
              fgetc / fputc   读出、写入单个字符
              fgets / fputs   读出、写入一行字符
              fread / fwrite  读出、写入指定长度数据
    3.关闭 -- fclose          


    man手册
    标准man手册分为8个章节:
    man 1        用户命令
    man 2        系统调用
    man 3        c函数库调用
    man 4        设备文件和特殊文件
    man 5        配置文件和格式
    man 6        游戏相关
    man 7        杂项,总述
    man 8        管理类命令

4.API函数接口
 
    1.fopen
    #include <stdio.h>
    FILE* fopen(const char *path, const char *mode);
    功能:
         流打开函数 (打开文件,并关联到一个流)
    参数:
        @pathname --要打开的文件的文件名(字符串形式)
        @mode --打开文件的操作模式
            r ---打开文件做读操作
                 注意:
                 文件必须存在 
                 
                 文件必须存在
                 
            r+   打开文件做写操作
            w   打开文件做读写操作
                 注意:
                 注意:
                 如果文件已经存在,则会将文件清空为0
                 如果文件不存在,则会创建一个新文件。
                 
            w+  打开文件做读写操作
                   如果文件已经存在,则在文件末尾进行写入 
                  如果文件不存在,则会创建一个新文件。
                 
            a+   打开文件做读写操作     
                 注意:
                 如果文件已经存在,则会将文件清空为0
                 如果文件不存在,则会创建一个新文件。

            a    打开文件做写操作
                 注意:
                 注意:
                 如果文件已经存在,则在文件末尾进行写入 
                 如果文件不存在,则会创建一个新文件。
            
            
    返回值:
       成功 FILE *  (文件流指针)
       失败 NULL 并且 设置 errno 表明错误原因 

    od -c 查看ASCLL中的字符
    cat 将文件中字符打印到终端

       
    流:
        数据从文件当中流入和流出所体现出来的字节流叫做流

        FILE 结构定义的对象(FILE * 指向的对象)称之为流对象,FILE *叫文件流指针。


        标准IO将对文件的操作转换成了对"流"的操作。
        所以,标准IO的文件相关的函数都是围绕着 FILE进行的。
         
          FILE * fp 
          FILE * fp;//流指针------关联一个文件   
          FILE * 实际上是指向了一块内存空间(缓存,fileno)
          
          
          FILE *fp <->【FILE结构体[缓存,fileno]】//堆区(malloc)
 
    2.fclose
      int fclose(FILE *fp);
      功能:
        关闭文件流指针 
      参数:
        fp:文件流指针 
      返回值:
        成功返回0 
        失败返回EOF(-1)
        
      注意:fopen操作完毕后使用fclose关闭,否则会产生内存泄漏
           不要重复调用fclose 
 
 
 
练习:
   用fopen实现一个touch的功能!
       (如何从命令行获取 文件名,然后进行操作)

#include <stdio.h>

int main(void)
{
	FILE *fp = NULL;

	fp = fopen("1.txt","r+");

	if (fp == NULL)
	{
		printf("没有这个文件!!!\n");
		return 0;
	}

	printf("存在这个文件!!!\n");
	
	char s[32] = "hello world!";
	int i = 0;

	while (s[i] != '\0')
	{
		fputc(s[i],fp);
		fputc(s[i],stdout);
		i++;
	}

	fputc('\n',stdout);

	fclose(fp);

	return 0;
}

    3.fputc
    int fputc(int c, FILE *stream);
    功能:
        向流中写入一个字符
    参数:
        c:要写入的字符
        stream:文件流指针
    返回值:
        成功返回 写入的字符ASCII码值
        失败返回 EOF

    练习:利用fputc实现在file.txt文件中写入hello world 

#include <stdio.h>

int main(void)
{
	FILE *fp = NULL;

	fp = fopen("1.txt","r+");

	if (fp == NULL)
	{
		printf("没有这个文件!!!\n");
		return 0;
	}

	printf("存在这个文件!!!\n");
	
	char s[32] = "hello world!";
	int i = 0;

	while (s[i] != '\0')
	{
		fputc(s[i],fp);
		fputc(s[i],stdout);
		i++;
	}

	fputc('\n',stdout);

	fclose(fp);

	return 0;
}

    
    //读 
    4.fgetc
    int  fgetc(FILE *stream);
    功能:
        从流中读取一个字符
    参数:
        stream:文件流指针
    返回值:
        成功返回读到字符的ASCII码值
        读到文件末尾 返回 EOF   
        失败返回EOF     EOF
        


 
    操作系统在运行一个程序时,会默认打开三个流:
        stdin        FILE*        标准输入流   ---->键盘
        stdout         FILE*        标准输出流   ---->屏幕
        stderr         FILE*        标准出错流   ---->屏幕
    
    gets scanf getchar ->  stdin 
    puts printf putchar -> stdout 
    perror -> stderr 
   

 
 
        
练习:  
    1.从终端输入数据并输出(fgetc、fputc)

#include <stdio.h>

int main(int argc, const char *argv[])
{
	if (argc < 2)
	{
		printf("恁弄啥嘞,加文件名( ⊙ o ⊙ )啊!\n");
		return 0;
	}
	FILE *fp = fopen(argv[1],"r");

	if (fp == NULL)
	{
		printf("没有这个文件!!!\n");

		return -1;
	}

	printf("存在这个文件!!!\n");
	
	int ret = 0;

	while (ret != -1)
	{
		ret = fgetc(fp);

		if (ret == -1)
		{
			break;
		}

		fputc(ret,stdout);
	}

	fclose(fp);

	return 0;
}


    
    2.用fgetc 从键盘获取数据   --- fgetc(stdin);
    将获取到的数据 写入到一个文件中。---fputc(ch,fp);
    
    如果输入q 表示输入结束!
    stdin --获取数据 --- fgetc  
    fp    --保存数据 --- fputc(ch,fp); // fp --- fopen     
 
    
            
    等价:
    ch = getchar();
    ch = fgetc(stdin);
    
    等价:
    putchar(ch);
    fputc(ch, stdout);

#include <stdio.h>


int main(int argc, const char *argv[])
{
	while (1)
	{
		fputc(fgetc(stdin), stderr);
	}

	//int ret = fgetc(stdin); ====> int ret = getchar();
	//fputc(ret, stdout);     ====>putchar(ret);
	

	return 0;
}

练习2: 
    cp  src.txt dest.txt 

#include <stdio.h>


int main(int argc, const char *argv[])
{
	if (argc < 3)
	{
		printf("Usage: ./a.out <src> <dest>\n");
		return 0;
	}
	
	FILE *srcfp = fopen(argv[1], "r");
	FILE *dstfp = fopen(argv[2], "w");
	if (NULL == srcfp || NULL == dstfp)
	{
		printf("fail fopen\n");
		return -1;
	}

	while (1)
	{
		int ret = fgetc(srcfp);
		if (EOF == ret)
		{
			break;
		}
		fputc(ret, dstfp);

	}

	fclose(srcfp);
	fclose(dstfp);

	return 0;
}


    

//面试题:    
fgetc()/fputc()面试题:
如何用最短的代码实现用户任意输入并打印输出。
要求用fgetc/fputc函数实现。

while(1) 
    fputc(fgetc(stdin),stdout);

while(fputc(fgetc(stdin),stdout)) 
    ;


//注意点:
fgetc()函数的结束判断。
1、EOF 宏来判断 ===》系统预制的文件结束标记
end of file  -1

5.fputs
    int fputs(const char *s, FILE *stream);
    功能:
           向流中写入一行字符串       
    参数: s 
               要写的信息,一般是固定的字符串或者有数据的数组。
           stream 
               要写入的目标文件流对象

    返回值:成功 nonnegative number on success
            失败 -1;
        
    注:
        不写入 '\0' 

#include <stdio.h>


int main(int argc, const char *argv[])
{
	FILE *fp = fopen("1.txt", "w");
	if (NULL == fp)
	{
		printf("fail fopen\n");
		return -1;
	}
	char str[] = {"hello world"};
	char *p = "hello world";
	int ret = fputs("hello world", fp);
	if (ret < 0)
	{
		printf("fail fputs\n");
	}
	fputs(str, fp);
	fputs(p, fp);


	fclose(fp);

	return 0;
}


    
    puts和fputs的区别:
        1.fputs不会自动增减\n
        2.puts 会多打印\n字符

    6.fgets
    //按行读写   按字符串读写 
    fgets  -- char ---> string 
    fputs  -- char ---> string

    char *fgets(char *s, int size, FILE *stream);
    功能:
          从stream流对象关联的文件中获取size大小字节的文本数据
      并存储到s对应的本地内存(栈区数组,堆区内存)
          
    参数: s    要存储数据的本地内存(栈,堆)
    
           size 要获取的数据长度,单位字节。
           stream 要获取的目标文件流对象,

            可以是stdin ,程序会阻塞等待
            如果是普通文件fp 则指向文件第一行数据
    返回值:成功 返回指向有效数据的首地址,一般等于s的地址
            失败 或者 文件末尾 NULL;

#include <stdio.h>

int main(int argc, const char *argv[])
{
	FILE *fp = fopen("1.txt", "r");
	if (NULL == fp)
	{
		printf("fail fopen\n");
		return -1;
	}
	
	char str[32] = {0};

	while (1)
	{
		char *p = fgets(str, 32, fp);
		if (NULL == p)
		{
			break;
		}
		printf("str = %s\n", str);
	}

	fclose(fp);

	return 0;
}

        注意:
        1.fgets能读取一行就读取一行
        2.fgets会读到n个数据,如果n个数据中存在\n字符则立即停止当
          前的读取操作,如果没有\n,则读取n-1个字符,最后一个存储\0    
        3.fgets每行读取的数据后面都有一个\n,在\n后面存放一个\0
                     12345
            buf[] = '1''2''3''4''5''\n''0'

        4.gets是危险的,因为没有规范读到数据的上限              
        5.gets会去掉从终端读入的\n字符 //也读走了\n 但是将 \n 去掉了 \n --> '\0'

作业

1. 使用fgets\fputs实现文件的拷贝 ./a.out src dst 要求:测试两种普通文件类型

#include <stdio.h>

int main(int argc, const char *argv[])
{
	if (argc < 3)
	{
		printf("error\n");
		return 0;
	}
	FILE *fp1 = fopen(argv[1],"r");
	FILE *fp2 = fopen(argv[2],"w");

	if (NULL == fp1 || NULL == fp2)
	{
		printf("error\n");

		return -1;
	}

	char s[10000];

	while (1)
	{
		char *p = fgets(s,1024,fp1);
		if (NULL == p)
		{
			break;
		}
		int ret = fputs(p,fp2);
		if (ret < 0)
		{
			printf("fail fputs\n");
		}

	}

	fclose(fp1);
	fclose(fp2);
	return 0;
}

2. 统计一个文本文件中,各种字符出现的次数

#include <stdio.h>

int main(int argc, const char *argv[])
{
	if (argc < 2)
	{
		printf("error\n");
		return 0;
	}

	int cnt[128] = {0};
	int ret = 0;

	FILE *fp = fopen(argv[1],"r");
	while (1)
	{
		ret = fgetc(fp);

		cnt[ret]++;

		if (EOF == ret)
		{
			break;
		}

	}

	for (ret = 0; ret < 128; ret++)
	{
		printf("cnt[%d] = %-3d ",ret,cnt[ret]);

		if (ret % 10 == 0)
		{
			printf("\n");
		}
	}

	printf("\n");

	return 0;
}


     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值