I/O进程学习——2

一、标准I/O:文件流API补充

fread

​ 函数功能:

​ 按照指定的大小,分块读取文件流的字符。

​ 函数原型:

​ size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

​ 函数参数:

参数 解释
ptr 将读取到的数据写入这个ptr指针的空间中(缓冲区)
size 读取的每块数据大小
nmemb 读取的总块数
stream 被读取数据的文件流

​ 函数返回值:

状态 解释
成功 返回值为 成功读取到的块数
失败/到文件结尾 返回值为 小于块数的数,也可能为0

tips: 判断fread是否读到文件结尾,也可以采用feof() 和 ferror()函数来进行判断。

fwrite

​ 函数功能:

​ 按照块数以及每块大小的指定数量,往文件写入数据

​ 函数原型:

​ size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);

​ 函数参数:

参数 解释
ptr 缓冲区(待写入文件流的数据源)
size 每块的大小
nmemb 总块数
stream 指针指向被写入文件

​ 函数返回值:

状态 解释
成功 成功写入的数据块数
失败 返回一个小于数据块数的数,也可能为0

fseek

​ 函数功能:

​ 从宏定义位置,开始偏移n(偏移量)个值

​ 函数内置宏定义:

宏名 解释
SEEK_SET 文件开头位置
SEEK_CUR 文件指针的当前位置
SEEK_END 文件结尾位置

​ 函数原型:

​ int fseek(FILE *stream, long offset,int whence);

​ 函数参数:

参数 解释
stream 需要偏移的文件指针
offset 偏移量(正或负,负往前偏移,正往后)
whence 偏移前的位置

​ 函数返回值:

状态 解释
成功 返回0
失败 返回1,并设置errno(全局错误号)

ftell

​ 函数功能:

​ 获取文件指针距离开头位置的距离长度(单位为字节)

​ 函数原型:

​ long ftell(FILE *stream);

fflash

​ 函数功能:

​ 强制刷新缓冲区

​ 函数原型:

​ int fflush(FILE *stream);

二、文件I/O

文件描述符

​ 操作系统提供给用户用于标识文件的一个特殊符号,这个符号是一个非负整数(>= 0)

​ stdin —— 0

​ stdout —— 1

​ stderr —— 2

1.系统调用函数

open

函数功能:

​ 打开文件,获取文件描述符

函数头文件:

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

函数原型:

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

函数参数:

参数 解释
pathname 文件路径
flags 文件权限标识
(mode_t) mode (int 宏定义)创建文件后,文件本身的权限,类似于chmod的用法

flags解释:

示例:ORDWR | O_CREAT | OTRUNC

flag 作用
O_RDONLY(必要之一) 只读打开
O_WRONLY(必要之一) 只写打开
O_RDWR(必要之一) 读写打开
O_APPEND 追加权限
O_CREAT 创建权限(不存在则创建)
O_TRUNC 截断打开(配合WR或者RDWR)

mode解释:

权限 八进制
可读、可写、可执行 7
只读 4
只写 2
只可执行 1

函数返回值:

read

函数功能:

函数头文件:

函数原型:

函数参数:

函数返回值:

write

函数功能:

函数头文件:

函数原型:

函数参数:

函数返回值:

close

函数功能:

​ 关闭文件,回收文件描述符(系统资源)

函数头文件:

​ #include <unistd.h>

函数原型:

​ int close(int fd);

函数参数:

​ fd 文件描述符

函数返回值:

状态 解释
成功 返回0
失败 返回-1,并设置errno

三、作业

1.文件加密

(1)加减数字
/*===============================================
*   文件名称:encrypt_1.c
*   创 建 者:青木莲华 
*   创建日期:2025年08月05日
*   描    述:利用加减值加密文件
================================================*/
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{ 
    FILE *fp = fopen("1.txt","r+");
    if(fp == NULL)
    {
        perror("fopen");
        return 0;
    }
    //缓冲区
    char buffer[1024] = {0};
    int i,len,ret;
    while(1)
    {
        fgets(buffer,sizeof(buffer),fp);
        ret = feof(fp);
        if(ret != 0)
        {
            break;
        }
        len = strlen(buffer);
        for(i = 0 ; i < len - 1 ; i++)
        {
            buffer[i] = (buffer[i] + 13) % 256;
        }
        fseek(fp,-len,SEEK_CUR);
        fputs(buffer,fp);
    }
    fclose(fp);
    return 0;
} 

运行截图

alt

(2)高四位和低四位交换
/*===============================================
*   文件名称:encrypt_2.c
*   创 建 者:青木莲华
*   创建日期:2025年08月05日
*   描    述:字符高位低位互换加密
================================================*/
#include <stdio.h>
#include <string.h>

//字符高四位与低四位互换
char exchange(char c)
{
    
    //高位 -> 低位  0000 1111
    char high = (c >> 4) & 0x0F;
    //低位 -> 高位  1111 0000
    char low = (c & 0x0F) << 4;

    return high | low;
}

int main(int argc, char *argv[])
{ 
    FILE *fp = fopen("2.txt","r+");
    if(fp == NULL)
    {
        perror("fopen");
        return 0;
    }
    char buffer[1024] = {0};
    int i,ret,len = 0;
    while(1)
    {
        memset(buffer,0,sizeof(buffer));
        fgets(buffer,sizeof(buffer),fp);
        ret = feof(fp);
        if(ret != 0)
            break;
        
        len = strlen(buffer);           
        for(i = 0 ; i < len - 1 ; i++)          //len - 1 是为了不加密换行符
            buffer[i] = exchange(buffer[i]);
        fseek(fp,-len,SEEK_CUR);               	//偏移量为上一行字符长度  负数往前偏移
        fputs(buffer,fp);
    }
    fclose(fp);
    return 0;
} 

运行截图

alt

(3)按照密钥加密
/*===============================================
*   文件名称:encrypt_3.c
*   创 建 者:青木莲华
*   创建日期:2025年08月05日
*   描    述:模拟密钥加密文件
================================================*/
#include <stdio.h>
#include <string.h>

//模拟密钥
const char key[8] = {'A','1','O','5','K','9','I','g'};

void encrypt(char *s,int len,int mode)
{
    int i;
    if(mode == 1)
        for(i = 0 ; i < len ; i++)              //加密
            s[i] = s[i] + key[i % 8];
    else if(mode == 2) 
        for(i = 0 ; i < len ; i++)
            s[i] = s[i] - key[i % 8];           //反向加密(解密)
}

int main(int argc, char *argv[])
{ 
    FILE *fp = fopen("3.txt","r+");
    if(fp == NULL)
    {
        perror("f_open");
        return 0;
    }
    char buffer[1024] = {0};
    int len,ret,mode = 0;
    printf("请选择模式: 1.加密  2.反加密\n");
    scanf("%d",&mode);
    if(mode < 1 || mode > 2)
    {
        printf("The mode error!\n");
        return 0;
    }
    while(1)
    {
        memset(buffer,0,sizeof(buffer));
        fgets(buffer,sizeof(buffer),fp);
        ret = feof(fp);
        if(ret != 0)
            break;
        
        len = strlen(buffer);
        encrypt(buffer,len - 1,mode);
        fseek(fp,-len,SEEK_CUR);
        fputs(buffer,fp);
    }
    fclose(fp);
    return 0;
} 

运行截图

2.完成图像操作

(1)自行制作图像
/*===============================================
*   文件名称:color.c
*   创 建 者:青木莲华 
*   创建日期:2025年08月05日
*   描    述:fwrite练习
================================================*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{ 

    FILE *fp = fopen("1.ppm","w");
    
    if(fp == NULL)
        return -1;
    char head[] = "P6\n1024 1024\n255\n";
    fwrite(head,sizeof(head)-1,1,fp);
    
    char color[3] = {255,255,255};
    int i,j;
    for(i = 0 ; i < 1024 ; i++)
    {   
        for(j = 0 ; j < 1024 ; j++)
        {
                color[0] = j % 255;
                color[1] = j % 255;
                color[2] = j % 255;
            fwrite(color,3,1,fp);
        }
    }
    fclose(fp);
    return 0;
} 

运行截图

alt

(2)图像的反差处理
/*===============================================
*   文件名称:color_bmp.c
*   创 建 者:青木莲华 
*   创建日期:2025年08月05日
*   描    述:利用fwrite和fread进行bmp图像处理
================================================*/
#include <stdio.h>

int main(int argc, char *argv[])
{ 
    FILE *fp_read = fopen("1.bmp","r");
    if(fp_read == NULL)
        return 0;
    FILE *fp_write = fopen("1_out.bmp","w");
    if(fp_write == NULL)
        return 0;

    //处理bmp文件头
    char head[54] = {0};
    fread(head,54,1,fp_read);
    fwrite(head,54,1,fp_write);
    //处理bmp文件长度和宽度
    int w = *(int *)&head[18];
    int h = *(int *)&head[22];
    printf("w = %d , h = %d\n",w,h);
    //读取bmp像素块
    char rgb[w * h][3]; 
    fread(rgb,w * h,3,fp_read);
    //负色处理
    int i;
    for(i = 0 ; i < w * h ; i++)
    {
        rgb[i][0] = 255 - rgb[i][0]; 
        rgb[i][1] = 255 - rgb[i][1];
        rgb[i][2] = 255 - rgb[i][2];
    }
    fwrite(rgb,w*h,3,fp_write);
    fclose(fp_read);
    fclose(fp_write);
    return 0;
} 

运行截图

alt

(3)图像打码
/*===============================================
*   文件名称:mosaic.c
*   创 建 者:青木莲华
*   创建日期:2025年08月05日
*   描    述:利用标准IO对图像进行打码处理
================================================*/
#include <stdio.h>

int main(int argc, char *argv[])
{ 
    FILE *fp_read = fopen("1.bmp","r");
    if(fp_read == NULL)
    {
        perror("fp_read");
        return 0;
    }
    FILE *fp_out = fopen("1_mosaic.bmp","w");
    if(fp_out == NULL)
    {
        perror("fp_out");
        return 0;
    }
    
    //处理bmp文件头
    char head[54] = {0};
    fread(head,54,1,fp_read);
    fwrite(head,54,1,fp_out);
    //处理bmp文件长度和宽度
    int w = *(int *)&head[18];
    int h = *(int *)&head[22];
    printf("图片宽:%d , 高:%d\n",w,h);
    //读取bmp像素块
    char buffer[h][w][3];
    fread(buffer,w * h,3,fp_read);
    
    //固定像素坐标轴
    int block_x = 100,block_y = 100;
    //填充坐标轴
    int x = 0,y = 0;
    //每个马赛克块的边长
    int msize = 25;
    //每行每列的马赛克块数
    int mcount = 16;
    //每个马赛克块的像素填充颜色
    char rgb[3] = {0};
    //对数据进行打码处理
    for(int i = 0 ; i < mcount ; i++)
    {
        for(int j = 0 ; j < mcount ; j++)
        {
            //计算行坐标
            x = block_x + j * msize;
            //计算列坐标
            y = block_y + i * msize;
            //给填充颜色赋值
            rgb[0] = buffer[y][x][0]; 
            rgb[1] = buffer[y][x][1];
            rgb[2] = buffer[y][x][2];
            for(int l = 0 ; l < msize ; l++)
            {
                for(int r = 0 ; r < msize ; r++)
                {
                    buffer[y+l][x+r][0] = rgb[0]; 
                    buffer[y+l][x+r][1] = rgb[1];
                    buffer[y+l][x+r][2] = rgb[2];
                }
            }
        }
    }
    fwrite(buffer,3,w*h,fp_out);
    printf("图像处理完毕。\n");
    fclose(fp_read);
    fclose(fp_out);
    return 0;
} 

运行截图

alt