IO进程学习——1

一、I/O进程的系统调用和库函数

alt

系统调用

  1. ​ 用户空间进程访问内核的接口

  2. ​ 把用户从底层的硬件编程中解放出来

  3. ​ 极大的提高了系统的安全性

  4. ​ 使用户程序具有可移植性

  5. ​ 是操作系统的一部分

库函数

  1. ​ 库函数为了实现某个功能而封装起来的API集合
  2. ​ 提供统- -的编程接口,更加便于应用程序的移植
  3. ​ 是语言或者应用程序的一部分

二、文件基础

定义

​ 文件:一组相关数据的有序集合

​ 文件名:这组数据集合的名称

文件类型

​ bcd-lps

​ b:块设备(磁盘)

​ c:字符设备(键盘、鼠标)

​ d:目录(文件夹)

​ -:普通文件

​ l:链接文件(符号链接/软链接)

​ inode(文件索引标号 唯一的) 硬链接和原文件inode号一样(等同于备份)

​ p:管道文件(主机间进程通信)

​ mkfifo 文件名 : 创建管道文件

​ s:套接字文件(跨主机进程间通信)

三、标准I/O

C语言标准库提供的一套用户和文件交互的API接口

alt

文件指针

FILE指针:每个被使用的文件都在内存中开辟一个区域, 用来存放文件的有关信息,这些信息是保存在一一个结构体类型的变量中,该结构体类型是由系统定义的,取名为FILE。

流(stream)

定义:所有的/0操作仅是简单的从程序移进或者移出,这种字节流,就称为流。 分类:文本流/二进制流。 标准I/O是带缓存的I/O---高级I/O

stdin:标准输入流

stdout:标准输出流

stderr:标准错误输出流

缓存(缓冲区)

行缓存:printf

​ 大小1024字节

​ 行缓存刷新条件:

​ 1.缓冲区满

​ 2.换行符

​ 3.强制刷新

​ 4.程序正常结束

全缓存:操作文件

​ 大小为4096字节

​ 全缓存刷新条件:

​ 1.缓冲区满

​ 2.强制刷新

​ 3.程序正常结束

无缓存:stderror 标准错误输出

API接口

  1. 打开文件:fopen

    ​ 函数功能:

    ​ 打开文件,在程序中获取操作文件的文件指针(流指针)

    ​ 函数头文件:

    ​ #include <stdio.h>

    ​ 函数原型:

    ​ FILE *fopen(const char *pathname, const char *mode);

    ​ 函数参数:

    ​ 1. pathname:文件路径

    ​ 2. mode:文件操作权限

    mode 作用
    r 只读打开
    r+ 可读、可写打开
    w 将文件截断(清零内容),没有文件则新建一个,然后写入
    w+ 读写文件,没有文件则新建一个
    a 在末尾追加,没有文件则新建一个
    a+ 追加文件,没有则创建一个

    ​ 函数返回值:

    ​ 文件打开成功:FILE类型指针

    ​ 文件打开失败:返回NULL,并且设置全局错误号(errno 默认无错误为0)

  2. 关闭文件:fclose

    ​ 函数功能:

    ​ 关闭文件,回收系统资源(文件打开存在上限,1024个)

    ​ 函数头文件:

    ​ #include <stdio.h>

    ​ 函数原型:

    ​ int fclose(FILE * stream);

    ​ 函数参数:

    ​ 1. stream:需要关闭的文件

    ​ 函数返回值:

    ​ 成功:返回 0

    ​ 失败:返回 EOF

  3. fgets:

    ​ 函数功能:

    ​ 从文件中获取内容到程序,按行获取

    ​ 函数头文件:

    ​ #include <stdio.h>

    ​ 函数原型:

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

    ​ 函数参数:

    ​ 1. s:程序存储获取内容的缓冲区首地址

    ​ 2. size:获取数据的长度(字节数)

    ​ 3. stream:获取文件的文件指针

    ​ 函数返回值:

    ​ 成功:返回缓冲区首地址

    ​ 失败:返回NULL

  4. fpust:

    ​ 函数功能:

    ​ 将缓冲区的字符写入到文件中

    ​ 函数头文件:

    ​ #include <stdio.h>

    ​ 函数原型:

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

    ​ 函数参数:

    ​ 1. 缓冲区(字符)

    ​ 2. 文件指针

    ​ 函数返回值:

    ​ 成功:返回非负整数

    ​ 失败:返回EOF

  5. feof/ferror

    ​ feof判断文件是否读到结尾,ferror判断文件是否读出错

    ​ int feof(const FILE *fp);

    ​ int ferror(const FILE *fp);

    ​ 没到文件结尾,没报错都返回0

    判断文件是否读完

    ​ if(!feof(fp) && !ferror(fp))

    ​ return 0;

  6. fgetc/fputc:

    ​ 函数功能:

    ​ 从文件中获取/写入一个字符

    ​ 函数头文件:

    ​ #include <stdio.h>

    ​ 函数原型:

    ​ int fgetc(FILE *stream);

    ​ int fputc(int c, FILE *stream);

    ​ 函数参数:

    ​ fgetc——stream:文件的文件指针

    ​ fputc——c:插入的字符

    ​ fputc——stream:文件的文件指针

    ​ 函数返回值:

    ​ 成功:返回获取/插入的那个字符的ASCII码

    ​ 失败:返回EOF

四、作业

1.实现文件拷贝

/*===============================================
*   文件名称:fcopy.c
*   创 建 者:青木莲华 
*   创建日期:2025年08月04日
*   描    述:文件拷贝
================================================*/
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{ 
    char pathname[32] = {0};
    char target[32] = {0};
    char buffer[1024] = {0};
    printf("请输入要拷贝的文件:\n");
    scanf("%s",pathname);
    printf("请输入目标文件:\n");
    scanf("%s",target);

    FILE *fp1 = fopen(pathname,"r");
    if(fp1 == NULL)
    {
        perror("error_msg");
        return -1;
    }
    FILE *fp2 = fopen(target,"w");
    while(fgets(buffer,1024,fp1) != NULL && !feof(fp1))
    {
		fputs(buffer,fp2);
    	memset(buffer,0,1024);
    }
    printf("copy success\n");
    fclose(fp1);
    fclose(fp2);
    return 0;
} 

运行截图

alt

2.模拟cp指令

/*===============================================
*   文件名称:fcopy.c
*   创 建 者:青木莲华 
*   创建日期:2025年08月04日
*   描    述:模拟cp命令拷贝文件
================================================*/
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{ 
    char pathname[32] = {0};
    char target[32] = {0};
    char buffer[1024] = {0};
    
    strcpy(pathname,argv[1]);
    strcpy(target,argv[2]);

    FILE *fp1 = fopen(pathname,"r");
    if(fp1 == NULL)
    {
        perror("error_msg");
        return -1;
    }
    FILE *fp2 = fopen(target,"w");
    while(fgets(buffer,1024,fp1) != NULL && !feof(fp1))
    {
		fputs(buffer,fp2);
    	memset(buffer,0,1024);
    }
    printf("copy success\n");
    fclose(fp1);
    fclose(fp2);
    return 0;
} 

运行截图

alt

3.实现用户管理

(1)登录 (2)注册

login.h

/*===============================================
*   文件名称:login.h
*   创 建 者:青木莲华
*   创建日期:2025年08月04日
*   描    述:模拟登录/注册功能
================================================*/
#ifndef __LOGIN_H__
#define __LOGIN_H__

#include <stdio.h>
#include <string.h>
#define OK 0            //登录成功
#define ERROR_ID -1     //账号错误
#define ERROR_PSW -2    //密码错误
#define ERROR_FILE -3   //文件错误
#define FILE_PATH "login_msg.txt"   //用户信息文件名

//登录方法
int login(const char *id,const char *password);
//注册方法
int reg(char *id,char *password);
#endif

login.c

/*===============================================
*   文件名称:login.c
*   创 建 者:青木莲华
*   创建日期:2025年08月04日
*   描    述:模拟登录/注册功能
================================================*/
#include "login.h"


//登录方法
int login(const char *id,const char *password)
{
    char temp_id[20] = {0};
    char temp_psw[20] = {0};
    char buffer[1024] = {0};
    FILE *fp = fopen(FILE_PATH,"r");
    if(fp == NULL)
    {
        perror("ERROR_MSG");
        return ERROR_FILE;
    }
    while(fgets(buffer,sizeof(buffer),fp) != NULL && !feof(fp))
    {
        sscanf(buffer,"%s : %s",temp_id,temp_psw);
        if(!strcmp(temp_id,id))
        { 
            if(!strcmp(temp_psw,password))
            {
                printf("----------LOGIN SUCCESS---------\n");
                printf("Welcome back <%s>\n",temp_id);
                fclose(fp);
                return OK;
            }
            else
            {
                printf("The password has wrong!\n");
                fclose(fp);
                return ERROR_PSW;
            }
        }
        memset(buffer,0,sizeof(buffer));
    }
    printf("The id has wrong!\n");
    fclose(fp);
    return ERROR_ID;
}

//注册方法
int reg(char *id,char *password)
{

    char temp_id[20] = {0};
    //char temp_psw[20] = {0};
    char buffer[1024] = {0};
    FILE *fp_read = fopen(FILE_PATH,"r");
    if(fp_read == NULL)
    {
        perror("ERROR_MSG");
        return ERROR_FILE;
    }
    //找是否账号有重复的
    while(fgets(buffer,sizeof(buffer),fp_read) != NULL && !feof(fp_read))
    {
        sscanf(buffer,"%s :",temp_id);
        if(!strcmp(temp_id,id))
        {
            printf("The id has exist!\n");
            fclose(fp_read);
            return ERROR_ID;
        }
    }
    fclose(fp_read);
    //追加内容
    FILE *fp_append = fopen(FILE_PATH,"a");
    sprintf(buffer,"%s : %s\n",id,password);
    if(fp_append == NULL)
    {
        perror("ERROR_MSG");
        return ERROR_FILE;
    }

    if(fputs(buffer,fp_append) == EOF)
    {
        printf("regist error!\n");
        return ERROR_FILE;
    }
    return OK;
}

main.c

/*===============================================
*   文件名称:main.c
*   创 建 者:青木莲华  
*   创建日期:2025年08月04日
*   描    述:模拟登录/注册功能
================================================*/
#include "login.h"


int main(int argc, char *argv[])
{ 
    int n = 0;
    char id[20] = {0};
    char psw[20] = {0};
    printf("-----------菜单-----------\n");
    printf("1.登录    2.注册    3.退出\n");
    printf("--------------------------\n");
    while(1)
    {   
        printf("选择选项 >: ");
        scanf("%d",&n);
        if(n == 3)
        {
            printf("---------退出成功---------\n");
            return 0;
        }
        switch(n)
        {        
            case 1:
            {
                printf("input your id >: ");
                scanf("%s",id);
                printf("input your password >: ");
                scanf("%s",psw);
                login(id,psw);
                break;
            }
            case 2: 
            {   
                printf("input your id >: ");
                scanf("%s",id);
                printf("input your password >: ");
                scanf("%s",psw);
                reg(id,psw);
                break;
            }
        }
        memset(id,0,sizeof(id));
        memset(psw,0,sizeof(psw));
    }

    return 0;
} 

运行截图

alt