[置顶] 20160228.CCPP体系详解(0038天)

程序片段(01):缓冲区.c
内容概要:缓冲区

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

//01.打开一个文件:
// 1.以"写入模式"打开一个"文本文件"
// FILE * pfw = fopen(arg1, arg2);
// arg1:文件路径+arg2:操作模式
// 2.向任何设备打印一段儿字符串:
// fputs(arg1, ar2);
// arg1:待打印的字符串+arg2:指向设备的指针
//02.严格区分缓冲区编程和非缓冲区编程:
// 1.当前这里的fpurs();只是写入进内存缓冲区当中,并为真正的写入到具体文件当中
// 属于缓冲区编程特点
// 2.由于这里使用到了内存缓冲区的概念,因此这种写入方式属于非实时写入状态
// 也就是内存缓冲区写入
// 3.非实时写入|内存缓冲区写入:
// 这种写入方式,必须要求使用fclose();执行关闭文件指针的同时,将内存缓冲区当中
// 的内容,强制由内存缓冲区当中刷入进设备文件当中
//注:缓冲区编程(非实时对应)与非缓冲区编程(实时对应)
int main01(void)
{
    FILE * pfw = fopen("D:\\TestSpace\\ TestData\\01.txt", "w");
    fputs("您好!男神", pfw);
    fclose(pfw);

    system("pause");
}


//01.文件常识:
// 1.C语言重点内容
// 2.C语言特点:
// (1).以前的所有数据存储于"内存"当中,一旦断电,数据就会丢失
// (2).QQ数据,配置文件数据的读写操作[写入文件,读取文件]
// (3).文件的用途:
// 1).保存程序的"配置信息"
// 2)."记录,数据"等等信息存放于文件当中
// 3).内存不够的情况之下,使用文件进行"永久存储"
//02.什么是外部介质?
// 1.无论是C语言还是C++语言,都将所有"外部设备"当做为"文件"进行抽象看待
// 2.所有"外部设备"-->"文件抽象"概念
// 3.除了内存以外,(磁盘&驱动&显示器&打印机)等等都被当中"文件"看待
// "驱动程序"也是通过"文件"的"读写操作"交互信息[文件模型]
//03.什么是记录文件?什么是流式文件?[文件逻辑结构决定]
// 1.记录文件:由具有一定结构的记录组成(定长和不定长)
// 例如:长度不固定的.pptx文件,.txt文件,.word文件
// 特点:具备有明确的结构特点:记录&word&txt&pdf
// 2.流式文件:由一个个字符(字节)数据组成
// 例如:视频文件传输的过程当中
// [没有明确的大小,视频聊天儿数据]-->实时传输-->动态特点-->单字节操作
//04.存储介质:
// 1.普通文件:保存于磁盘之上的文件
// 2.设备文件:C语言将所有的设备都当做文件进行抽象模拟对待
//05.数据的组织形式:
// 1.文本文件
// 表现形式:字符-->过渡形式:ASCII-->存储形式:二进制
// 2.二进制文件
// 表现形式:二进制-->过渡形式:二进制-->存储形式:二进制
// 举例:123的两种存储方式
// 字符串:123
// ASCII:文本文件的存储方式[字符-->ASCII-->单字节-->二进制]
// '1' '2' '3'-->49 50 51-->占用三个字节
// 49:0011 0001
// 50:0011 0010
// 51:0011 0011
// 二进制存储方式:直接存储方式
// 01111 1011(123-->整数-->整体二进制)
// char:不同的解析方式,导致存储方式不一样
// 0111 1011
// short:
// 0000 0000 0111 1011
// int:
// 0000 0000 0000 0000 0000 0000 0111 1011
//注:文本方式:就是一个一个字符映射为ASCII码进行存储,
// 进制方式:就是直接的内存存储形式进行存储
//06.二进制文件的差别在哪里?
// 1.二进制文件是按照"内存数据"方式进行存储的[也就是0&1模式存储特点]
// 2.文本文件是按照"ASCII码"方式进行存储的
// 区别:保存"文本文件"的时候使用的是"txt",保存"二进制文件"的时候使用"exe"
// 扩展名决定文件的保存形式
//07.文件可以起到什么样儿的作用?
// 1.文件<-->内存:防止不断的编写
// 2.文件和程序的分离:不同的程序可以读取相同的数据&数据共享特点
// 程序和数据的分离
// 3.保存程序的运行结果:查询开房数据的保存方式
//08.文件的标识:
// 1.文件名:注意操作系统占用的文件名(设备占用名)
// CON&COM1&COM2&LPT1&LPT2&PRN-->指定的"设备名无效"
// 2.在C语言当中,会将所有的"设备"都抽象当做"文件"进行处理[内存设备除外]
// 无论是否携带扩展名,都不可以使用系统定义的"操作设备名称"进行使用
//09.流的概念;
// 1.动态特点:相互"传递数据",大小"不可确定"
// 输出流&输入流-->操作便捷(非定长数据)
// 2.一般情况下两个程序之间进行通信的时候,进行文件传输的时候
// 都需要使用到流的概念-->文件传输流
// 3.文件流:视频聊天儿数据
//注:文件不仅只有"磁盘"上面的"定长"文件概念,还同时包含"文件流"的"非定长"特点
//10.缓冲区:
// 1.什么是缓冲区?有什么特点?
// (1).磁盘查找数据特点:读道
// (2).内存查找数据特点:寻址
// 2.文件处理的情况之下有两类缓冲区:
// 自动缓冲区&手动缓冲区(缓冲区编程范畴之下)
// 3.磁盘读道非常复杂-->迅雷下载非常伤硬盘
// -->频繁的读写磁盘-->缓冲区的概念[减少读取磁道的次数]
// -->火车票购买原理&进程读写原理(临时缓冲区原理,减少读取次数!)
// -->内存当中开辟缓冲区:写入的数据先进行"数据汇集"
// 最终进行"一并的操作",避免多次"重复读取磁盘"
// 特点:保护磁盘文件系统,避免伤害磁盘的次数
// 4.缓冲区编程与非缓冲区编程:
// 高级文件系统
// 系统会自动开辟缓冲区[fgets();fputs();-->实质是缓冲区操作]
// 程序当中设定缓冲区:
// 自我设定,进行实时读写操作
//11.缓冲文件系统&非缓冲区文件系统:
// 非缓冲文件系统-->把什么样儿的设备都当做文件进行处理
// -->缓冲区溢出情况-->像键盘&屏幕这样儿的文件系统就不能
// 设定"文件缓冲区大小",让其一会儿再进行操作-->这种情况就
// -->需要进行"实时操作"-->缓冲区|非缓冲区编程
// -->缓冲区与实时编程的特点
//12.文件重定向:操作系统执行的操作
// 1.文件重定向和磁盘之间的关系
// 2.什么是文件重定向?文件重定向又起到了什么样儿的作用?

程序片段(02):文件重定向.c
内容概要:文件重定向

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

//01.缓冲区编程:
// 1.默认缓冲区+指定缓冲区
// 2.标准缓冲区+自定缓冲区
//注:执行程序的时候,遇到空格就会跳过(指令截取)
int main01(void)
{
    char str[1024] = { 0 };
    gets(str);//获取
    puts(str);//输出
    system(str);//执行

    system("pause");
}

//02.缓冲区编程:
// 1.常见的标准缓冲区:
// stdin:从键盘获取
// stdout:显示屏幕
// stderr:x显示器错误(不可重定向)
// 2.针对于(gets();与puts();)和(fgets();与fputs();)的对比:
// (1).这里的(fgets();与fputs();)和上面的(gets();与puts();)执行执行效果一致
// 其实,(gets();与puts();)只是(fgets();与fputs();)的一个特殊实例
// (2).因为,键盘和屏幕都是一个特殊的设备,也就是一个特殊的文件而已
// fgets();和fputs();需要手动指定特殊文件设备,而gets();和puts();默认指定
int main02(void)
{
    char str[1024] = { 0 };
    fgets(str, 1023, stdin);//键盘获取到文件
    fputs(str, stdout);//屏幕显示文件数据
    system(str);

    system("pause");
}

//03.比较两种数据获取和打印方式:
// fgets();与fputs();(gets();与puts();)
// 标准设备名称在后
// fscanf();与fprintf();(scanf();与printf)
// 标准设备名称在前
//注:将所有设备当中文件进行处理!
int main03(void)
{
    char str[1024] = { 0 };
    //scanf("%s", str);
    //printf("%s", str);
    fscanf(stdin, "%s", str);
    fprintf(stdout, "%s", str);
    system(str);

    system("pause");
}

//04.标准错误输出设备:
// stderr:指向的是输出设备
//注:该设备内容不可实现重定向操作!
// 字符串录入的域宽不能限制输入字符长度,只能控制输入字符的格式!
int main04(void)
{
    char str[1024] = { 0 };
    //scanf("%s", str);
    //printf("%s", str);
    fscanf(stdin, "%s", str);
    //fprintf(stdout, "%5s", str); 
    fprintf(stderr, "error = %s \n", str);
    system(str);

    system("pause");
}

//01.文件"输入输出"总结:
// 可携带空格:(后文件)
// fgets(str,1024,stdin);------fputs(str,stdout);
// (特例:gets(str);-------puts(str);)
// 不可携带空格:(前文件)
// fscanf(stdin,"%s",str);-----fprintf(stdout,"%s",str);&fprintf(stderr,"\nerror=%s",str);
// (特例:scanf("%s",str);------printf("%s",str);)
//注:strerr所指向的输出设备内容不可实现重定向!
//02.文件的输入输出需要经过安全检查
// #define _CRT_SECURE_NO_WARNINGS
//03.文件重定向:(执行操作&暂停窗口)tasklist&pause
// 1.关系流程:
// 控制台-->执行程序-->输入内容-->显示内容-->暂停窗口
// 2.文件输入:
// (1).文件重定向.exe < 2.txt--netstat[输入状态:屏幕(stdin)]
// (2).文件重定向.exe < 2.txt >4.txt[输入状态:文件(File)]
// 3.文件输出:
// (1).文件重定向.exe > 1.txt tasklist;重写操作
// (2).文件重定向.exe >> 1.txt tasklist;追加操作
//04.文件重定向的原理:
// 1.文件指针:指针打开文件-->描述文件信息(本质:结构体)
// 2.文件指针:实质-->结构体-->GB&位移&文件标识是否使用&临时文件名
// 包含了文件的很多信息:FILE表示指向结构体的指针[实质:操作文件]
//05.文件类型的指针:
// 打开文件之后,自动创建了一个结构体,并返回指向该结构体的文件指针,所有文件的
// 信息都保存在文件结构体当中-->文件指针是由操作系统进行管理的
//06.文件系统使用特点:
// stdin:标准输入文件指针,系统分配为"键盘"
// stdout:标准输出文件指针,系统分配为"屏幕"
// stderr:标准错误输出文件指针,系统分配为"显示器"
//07.文件查找所用到的两个函数:
// fgets()-->A:内存地址,B:文件长度,C:文件指针[跨平台特性的文件指针]
// fputs();
//08.scanf();&pfintf();//属于fscanf();&fprintf();的特殊情况
// 1.stdout&stdin:说明C语言中所有的设备都当做文件进行处理
// 2.特点:有一个东西不能够进行重定向到文件,就是stderr
// stderr不能重定向到文件当中[文件重定向.exe>x.txt tasklist]
// 只能在屏幕显示,不能够重定向到文件(由于stderr对应的是显示器设备)
// 如果某些文件不想让它被重定向到文件,就可以使用stderr文件指针
//09.细节问题:
// 1.C语言将所有的设备都当做文件进行处理
// 2.FILE就是文件类型的结构体:
// struct _iobuf
// {
// char *_ptr;//当前缓冲区内容指针
// int _cnt;//缓冲区还有多少个字符
// char *_base;//缓冲区的起始地址
// int _flag;//文件流的状态,是否错误或者结束
// int _file;//文件描述符
// int _charbuf;//双字节缓冲,缓冲两个字节
// int _bufsize;//缓冲区大小
// }
// typedef struct _iobuf FILE
//10.问题:
// 1.文本文件和二进制文件的差别是什么?
// 存储方式不同(对于换行符的处理方式不一样)
// 2.记录文件和流式文件:
// 键盘是流式文件,时时刻刻的输入原理(动态对应)
// 3.流的概念?
// 显示器显示内容&键盘源源不断的等待输入内容
// 4.缓冲区概念?
// 汇集操作,避免过度的读写磁盘,伤害磁盘
// 5.区分缓冲区编程还是非缓冲区编程?
// 是否是实时进行的数据写入操作
// 6.文件类型的结构体,深入细节!
// 7.文件编程:
// 实时&非实时-->FILE类型的文件指针是否实时编程,因为依赖于缓冲区
// 缓冲区编程-->非实时操作-->非流式概念
// 8.记住特点:跨平台
// stdin:键盘-->stdout:屏幕-->stderr:显示器
//11.细节描述:
// fopen();参数列表-->以什么样儿的模式打开一个文件
// r&rb w&wb
// a/ab普通追加
// r+/rb+读写&w+/wb+
// a+/ab+读写的追加
// fclose();强制操作缓冲区内容到文件

程序片段(03):01.文件操作.c+02.加密.c+03.二进制加密.c
内容概要:文件字符读写

///01.文件操作.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

//01.文件指针的构建要点:
// 1.区分文件类型:
// 文本文件or进制文件
// 2.区分读写模式:
// 读取模式or写入模式
// 3.区分是否追加:
// 追加模式or覆盖模式
//02.文件单字符读取写入:
// fgetc();与fputc();
//03.关于文件结尾要点:
// 1.无论是文本文件还是进制文件:
// 结尾判断方式都是feof();
// 2.文本文件的明显结束标识是EOF
//注:fgetc();与fputc();函数调用一次,文件指针移动一个字符尺寸
//注:feof();只是判断文件指针所指向的字符是否为结束标识!
// 不会进行文件指针的移动
//注:区分文件指针的移动或者不移动情况
int main01(void)
{
    FILE * pfr = fopen("D:\\TestSpace\\TestData\\01.txt", "r");
    //char chr = fgetc(pfr);
    while (!feof(pfr))
    {
        char chr = fgetc(pfr);
        putchar(chr);
    }

    fclose(pfr);
    system("pause");
}

//04.为了防止出现:"另外一个程序正在使用此文件,进程无法进行访问"语句的出现
// 尽量使用fclose();关闭掉文件指针,避免文件流占用!
int main02(void)
{
    FILE * pfr = fopen("D:\\TestSpace\\TestData\\Q.txt", "r");
    FILE * pfw = fopen("D:\\TestSpace\\TestData\\QW.txt", "w");
    while (!feof(pfr))
    {
        char chr = fgetc(pfr);//读取单个字符,移动文件指针
        fputc(chr, pfw);//写入单个字符,移动文件指针
    }
    fclose(pfr);
    fclose(pfw);
    system("D:\\TestSpace\\TestData\\QW.txt");

    system("pause");
}

//05.二进制文件的读写操作:
// 1.文件复制的时候所涉及到的复制细节:
// 允许多复制一个字节,但是加解密情况之下既不允许多一个字节也不允许少一个字节的情况,
// 避免加解密过程出现错误(简单加解密情况的剖析)
// 2.加解密情况不允许原因,因为为了防止像EOF这样的文本文件结束标识符被写入进去,于是就
// 多了一个文件结束标识符EOF
int main03()
{
    FILE * pfr = fopen("D:\\TestSpace\\TestData\\Q.exe", "rb");//以只读模式打开一个文件指针
    FILE * pfw = fopen("D:\\TestSpace\\TestData\\FQ.exe", "wb");//以只写模式打开一个文件指针
    while (!feof(pfr))
    {
        char chr = fgetc(pfr);//读取单个字符并移动文件指针
        fputc(chr, pfw);//写入单个字符并移动文件指针
    }
    fclose(pfr);
    fclose(pfw);
    system("D:\\TestSpace\\TestData\\FQ.exe");

    system("pause");
}



//01.操作的不同所导致的问题&不同的参数:
// "文本文件"操作模式&"二进制文件"的操作模式
//02.fclose();//关闭文件的作用,用于将缓冲区当中的
// 内容强制刷入到指定文件当中
//03.文件字符读写:
// 1.字符读写函数:fgetc();&fputc();(特例:getchar();与putchar();)
// 2.读写特点:
// (1).每次读写一个字符[单位:字节]
// (2).在读写操作完成之后,再进行字符指针的移动操作
//04.两种方式的案例:
// 1.FeiQiu二进制文件操作案例:
// Q.exe&&Q.txt[Hello World Hello China Hello nanshen]
// 2.复制-->加密动作:字符-->字节
// FeiQiu.exe:二进制文件
// Q.txt文本文件
//05.fgetc();&fputc();的使用:
// 1.读取特点:fopen(path,"r&rb");
// 2.fclose();//关闭文件指针
//06.文件指针的概念:
// 1.整段整段的文件-->文件结束符[EOF:-1]
// 2.读取特点:从开头逐个进行读取,知道读取到EOF结束符为止
//06.注意事项:
// 1.某些宽字符文件的读取特点:
// 2.fgetc();只用于处理窄字符
//07.复制文件:
// 1.文件很大的情况之下需要使用到多线程
// 2.需要两个文件指针:读取指针,写入指针
///02.加密.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

//01.文本文件操作模式:
// 1.EOF是一个宏定义,本质是-1我们的文件都是以EOF作为[文件结束标识符]
// 2.这里的while循环格式会导致最终的EOF文件结束标识符被写入进目标文件
// 因为这里是先写入,再执行的判断操作
// 3.由于文本文件的最后一个字符会是文本文件的结束标识符EOF,因此某些时候
// 该文本文件打开是乱码(如果是二进制文件,还有可能导致其不能正常运行)
int main04(void)
{
    FILE * pfr = fopen("D:\\TestSpace\\TestData\\Q.txt", "r");
    FILE * pfw = fopen("D:\\TestSpace\\TestData\\QW.txt", "w");
    char chr = '\0';

    //while (EOF != chr)//判定的是写入状态字符
    //{
    // chr = fgetc(pfr);
    // fputc(chr, pfw);//先写入,再读取
    //}

    //while (EOF != chr)
    //{
    // chr = fgetc(pfr);
    // if (EOF != chr)
    // {//先判断,再写入
    // fputc(chr, pfw);//
    // }
    //}

    //while (!feof(pfr))
    //{//先判断,再读取和写入
    // chr = fgetc(pfr);
    // fputc(chr, pfw);
    //}

    while (EOF != (chr = fgetc(pfr)))
    {//终极简化形式
        fputc(chr, pfw);
    }

    fclose(pfr);
    fclose(pfw);
    system("D:\\TestSpace\\TestData\\QW.txt");
    system("pause");
}

//02.关于文本文件的加解密问题分析:
// 1.由于文本文件是以EOF(-1)作为文件的结束标识
// 因此如果文本文件当中如果出现了(-1)就会导致文本文件操作结束
// 2.然而,在文件进行加密过程当中,比较容易出现和(-1)ASCII码值相同
// 的情况,因而,极其容易导致加密之后的的文件,出现解密字节数不够
// 3.还有可能出现回车符的问题:
// 写入到文件:\r\n
// 读取到内存:\n
// 因为导致,字节数差距的情况发生
void encrypt(char * pSrcPath, char * pDesPath)
{
    FILE * pfr = fopen(pSrcPath, "r");
    FILE * pfw = fopen(pDesPath, "w");
    char chr = '\0';//建议使用int类型,较大范围内避免-1的产生(越界产生)
    while (EOF != (chr = fgetc(pfr)))
    {
        chr += 1;//加解密位置
        fputc(chr, pfw);
    }
    fclose(pfr);
    fclose(pfw);
}

void decrypt(char * pSrcPath, char * pDesPath)
{
    FILE * pfr = fopen(pSrcPath, "r");
    FILE * pfw = fopen(pDesPath, "w");
    char chr = '\0';
    while (EOF != (chr = fgetc(pfr)))
    {
        chr -= 1;
        fputc(chr, pfw);
    }
    fclose(pfr);
    fclose(pfw);
}

int main05(void)
{
    char * pSrcPath = "D:\\TestSpace\\TestData\\Q.txt";
    char * pEnPath = "D:\\TestSpace\\TestData\\QEn.txt";
    char * pDePath = "D:\\TestSpace\\TestData\\QDe.txt";
    encrypt(pSrcPath, pEnPath);
    decrypt(pEnPath, pDePath);

    system("pause");
}



//01.精确的加密和解密:
// 1.文件的加密与解密&字符串的加密与解密
// 2.让同一个函数实现加解密运算[异或运算]
// 3.文本加密-->进制加密
// 4.字节加密比文本加密更好一些(精准&跨平台)
//02.复制之后多余的部分其实是EOF结尾符:
// 拷贝的时候可以,但是加密的时候不能够多一个EOF结尾符
//03.加密与解密分为两种:
// 非密码加密&密码加密[破解情况]
///03.二进制加密.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

char * pSrcPath = "D:\\TestSpace\\TestData\\Q.exe";
char * pEnPath = "D:\\TestSpace\\TestData\\QEn.exe";
char * pDePath = "D:\\TestSpace\\TestData\\QDe.exe";

//01.加解密采用同一函数进行实现:
// 通常采用异或的运算特性实现
//02.文件结束判断标识:
// 1.针对于文本文件:
// 可以采取EOF作为文本文件结束标识进行判断
// 2.针对于所有文件:
// 都可以采用feof();函数进行文件是否操作的尾部的判断
void enDeCrypt(char * pSrcPath, char * pDesPath)
{
    FILE * pfr = fopen(pSrcPath, "rb");
    FILE * pfw = fopen(pDesPath, "wb");
    if (NULL == pfr || NULL == pfw)
        abort();
    //char chr = '\0';
    //while (EOF != (chr = fgetc(pfr)))
    //{//1.某些特殊的情况之下,在chr执行完成异或运算之后,会产生特殊字符-1,也就是文件结束标识符EOF,因此读取状态结束,导致写入加密数据不完整
    // char newChr = chr ^= 3;//2.因此这句话就是为了防止读取到的chr被异或为-1,保留原始数据
    // fputc(newChr, pfw);//3.这里的EOF只是用于文本操作,二进制也有可能在中间过程当中产生-1,因此加解密操作的情况之下不能采用EOF作为文件结束判断标识
    //}
    while (!feof(pfr))
    {//feof();无论是文本文件还是二进制文件,都能够精准的操作到文件的末尾
        char chr = fgetc(pfr);
        chr ^= 3;
        fputc(chr, pfw);//加解密之后会多出单个字节(文件操作结束标识!)Windows系统之下会产生,Linux系统之下不会产生
    }
    fclose(pfr);
    fclose(pfw);
}

int getFileSize(char * pFilePath)
{
    FILE * pfr = fopen(pFilePath, "rb");
    if (NULL == pfr)
        return -1;
    int size = -1;//由于二进制文件有一个结束标记,因此需要采用-1作为统计
    while (!feof(pfr))//标准的文件结束判断函数
    {
        char chr = fgetc(pfr);
        //if (EOF == chr)
        //{//二进制文件的结束标识符不EOF,但由于二进制文件当中可能会有-1的补码存在,因此会出现很多EOF显示出来
        // puts("EOF");//这就是为什么二进制文件万万不能以EOF作为结束标识符判断的原因
        //}
        ++size; 
    }
    fclose(pfr);
    return size;
}

int getFileSizeBySeek(char * pFilePath)
{
    FILE * pfr = fopen(pFilePath, "rb");
    if (NULL == pfr)
        return -1;
    fseek(pfr, 0, SEEK_END);//文件指针移动到文件的末尾
    int length = ftell(pfr);//当前文件指针距离缓冲区头部的距离
    fclose(pfr);
    return length;
}

int main06(void)
{
    //enDeCrypt(pSrcPath, pEnPath); 
    //enDeCrypt(pEnPath, pDePath);

    //printf("FeiQ.size = %d \n", getFileSize(pSrcPath));
    //printf("FeiQ.size= %d \n", getFileSizeBySeek(pSrcPath));

    system("pause");
}



//01.二进制文件加解密:加解密应用最多的地方[二进制文件的加解密操作]
// FeiQ.exe-->加密-->再次运行-->加密运用最多的地方-->密码加密
//02.FeiQiu的加解密原理:
// 1.原始长度-->整体修改数据
// 2.密码一段-->推出一段儿的处理
// 一般情况之下不能够进行整除-->字符加密
//03.两种方法:
// 1.密码加密
// 2.无密码加密
//04.跳过360的安全检查就需要使用到加密常识!
// 加密之后的文件不能正常的执行和解析(无法进行测试)
//05.加密结果可能导致文件变大,也可能导致文件变小:
// EOF不适用于二进制文件判断结束,feof();通用结束判断方式!
//06.操作二进制文件都需要获取二进制文件的大小

程序片段(04):01.加解密文本.c+02.加解密二进制.c
内容概要:加密工具

///01.加解密文本.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char * pSrcPath = "D:\\TestSpace\\TestData\\BaiDu.txt";
char * pEnPath = "D:\\TestSpace\\TestData\\BaiDuEn.txt";
char * pDePath = "D:\\TestSpace\\TestData\\BaiDuDe.txt";

//01.统计文件尺寸:
// 1.最好以"二进制"的"只读模式"打开文件实施字节统计
// 2.最好使用标准的判断"文件结尾函数"(跨平台|跨文件)
int getFileSize(char * pFilePath)
{
    FILE * pfr = fopen(pFilePath, "rb");//二进制,只读
    if (NULL == pfr)
        abort();
    //统计字节数的方式一:借助文件指针(效率高)
    // 移动指向文件缓冲区的文件指针到缓冲区的末尾
    // 计算当前文件指针距离文件开头的距离
    //fseek(pfr, 0, SEEK_END);
    //int length = ftell(pfr);
    //统计字节数的方式二:挨个挨个进行统计(效率低)
    int length = 0;
    int chr = 0;
    while (EOF != (chr = fgetc(pfr)))//fgetc();的返回值是int类型,文件获取字符成功返回0,文件获取字符失败返回-1
    {//对于文本文件而言,文本文件的结束标识符为EOF(-1)
        //putchar(chr);
        ++length;
    }
    fclose(pfr);
    return length;
}

//02.文本文件方式写入:
// 1.回车符('\n'),在Win系统下,写入文件的时候被写入为两个字符('\r''\n')
// 因此,导致写入文件的尺寸要大于内存读取时的尺寸
// 2.在文本文件当中,写入不可见字符,依然不可见
// 但是其位置依旧会被保留下来
// 3.这里写入五个'\n'到文本文件当中,结果文本文件的尺寸依然为10个字节
// 说明了Win系统中内存('\n')写入到硬盘之后变为了('\r\n')
void txtWrite()
{
    FILE * pfw = fopen("D:\\TestSpace\\TestData\\01.txt", "wt");
    for (int i = 0; i < 5; ++i)
    {
        fputc('\n', pfw);
    }
    fclose(pfw);
}

//03.二进制文件方式写入:
void binWrite()
{
    FILE * pfw = fopen("D:\\TestSpace\\TestData\\02.txt", "wb");
    for (int i = 0; i < 5; ++i)
    {
        fputc('A', pfw);
    }
    fclose(pfw);
}

//04.二进制文件方式读取
void txtBinRead()
{
    FILE * pfr = fopen("D:\\TestSpace\\TestData\\01.txt", "rt");
    char chr = '\0';
    while (EOF != (chr = fgetc(pfr)))
    {//文本文件方式
        //printf("%c", chr);//不可见字符
        printf("%d", chr);//内存1:硬盘2(Win系统特点)
    }
    //FILE * pfr = fopen("D:\\TestSpace\\TestData\\02.txt", "rb");
    //while (!feof(pfr))
    //{//通用方式
    // printf("%c", fgetc(pfr));
    //}
    fclose(pfr);
}

//05.两个特殊的转义字符:
// '\r'--->ASCII:13
// '\n'-->ASCII:10
int main01(void)
{
    //printf("%d, %d \n", '\r', '\n');

    //printf("BaiDu.size = %d \n", getFileSize(pSrcPath));

    //txtWrite();

    //binWrite();

    txtBinRead();

    system("pause");
}

//06.关于fgetc();和fputc();函数的详解:
// 1.获取或输出单个字符
// 2.返回值:正常返回字符+异常返回-1
//注:俩个函数的返回值类型是int类型,因此为了避免出现溢出情况,建议使用int类型接收
//注:fgetc();函数的返回值采用int类型进行接收的原因,是为了防止文件指针在读取过程当中中断
// (进行异或运算的情况之下)防止遇到溢出字符-1-->溢出现象-->
// char类型可能会出现溢出情况,int类型不会出现溢出情况
void enDeCrypt(char * pSrcPath, char * pDesPath)
{
    FILE * pfr = fopen(pSrcPath, "r");//任意只读模式
    FILE * pfw = fopen(pDesPath, "w");//任意只写模式
    if (NULL == pfr || NULL == pfw)
        abort();
    //char chr = '\0';//异或运算可能导致溢出!
    int chr = -1;//异或运算不能导致溢出-->读取过程是不可能出现溢出情况的(字符ASCII码值限制)
    while (EOF != (chr = fgetc(pfr)))
    {//文本文件标准操作模式-->需要准确适用int类型+EOF-->区分程序结构的不同所导致的判断不同
        //chr ^= 3;//溢出情况容易发生的位置-->其实这种程序结构使用int类型和chr类型结果一样!
        fputc(chr ^ 3, pfw);//由于采用异或运算符,所以可能产生'\n'所对应的ASCII码值,因此影响文件尺寸大小!
    }//这儿加密过程一帆风顺,但是解密的过程就不一定一帆风顺了,因为异或运算可能会产生文本文件结束标记(溢出情况)
    fclose(pfw);//因此,在解密过程当中,可能会出现解密中断现象的发生
    fclose(pfr);//解密过程中间读取到了EOF的实质-1情况,因此解密失败!
}

//07.按照指定密码进行加解密:
// 1.加解密-->(密码)加解密-->整体比对
// 2.加密方式:获取文件尺寸-->单个字符Len
// 3.加解密最好采用二进制方式进行,这样不会出现溢出情况,不会丢失数据
// 加密结果和解密结果的尺寸一致(文本方式执行,可能通常会变大)
//注:加解密采用二进制,防止内存尺寸不一致!(定长加解密算法)
void enDeCryptByPass(char * pSrcPath, char * pDesPath, char * pPassStr)
{
    FILE * pfr = fopen(pSrcPath, "rb");
    FILE * pfw = fopen(pDesPath, "wb");
    if (NULL == pfr || NULL == pfw)
        abort();
    int pSrcLen = getFileSize(pSrcPath);//内存字节
    int pPasLen = strlen(pPassStr);//密串字节
    int quotient = pSrcLen / pPasLen;
    int remainder = pSrcLen % pPasLen;
    for (int i = 0; i < quotient; ++i)//多少个子串
    {
        for (int j = 0; j < pPasLen; ++j)
        {//避免异或运算结果溢出,因此使用int类型进行接收
            int chr = fgetc(pfr);//获取单个字符进行以后运算,体现了一种随机性,较为复杂的以后加解密方式
            fputc(chr ^ pPassStr[j], pfw);//按照子串的尺寸移动文件指针,加密运算,写入操作
        }
    }
    for (int i = 0; i < remainder; ++i)
    {//自适应方式
        int chr = fgetc(pfr);
        fputc(chr ^= pPassStr[i], pfw);
    }
    fclose(pfr);
    fclose(pfw);
}

int main02(void)
{
    //enDeCrypt(pSrcPath, pEnPath);
    //enDeCrypt(pEnPath, pDePath);

    enDeCryptByPass(pSrcPath, pEnPath, "BingQiuChe");
    enDeCryptByPass(pEnPath, pDePath, "BingQiuChe");

    system("pause");
}



//01.加密工具的设计:
// 文件类型:
// "文本"问题&"二进制"问题
//02.文本文件加解密:
// 1.是否需密码:
// 密码&非密码
// 2.字符串加密:
// 对齐和不对齐
//03.加密文件:
// 基本操作:读取文件大小(文本or进制)-->两种方式
//04.文本文件\r\n换行-->文本文件读取的时候是\n方式
// 内存:\n-->硬盘:\r\n
//05.统计文本字节数原理:
// 回车特点!!!!!
// 文本文件:出现不匹配
// 写入\r\n-->读取\n-->字符读取情况容易丢失数据
// 二进制文件:完全对应
// 写入:\r\n-->读取\r\n
// 所以获取文件包的真正大小,理论上都是使用rb进行内容读取
//05.\n的ASCII是10-->\r\b的ASCII是13,10
//06.读取文件大小,理论上都是rb,如果一定要使用r,如果字符等于\n,需要进行额外的++
// 相当于补充\r的一次情况在文件中占用的一次(内存解析:\n-->硬盘解析:\r\n)
//注:补充的一次实质上是补充'\r'这个转义字符所在硬盘当中占用的单字节内存尺寸!
//07.文件读写的两种方式:
// 1."宽窄字符"特点,非常重视:"文本文件"的处理方式
// 文本文件的读写切忌注意宽窄字符问题!
// 2.fgetc();//文本文件?制表符?Unicode[宽字符文本文件处理]
// 如果使用Unicode就不能使用fopen();应当使用sfsopen();
// 3.字符读取方式:
// 窄字符读取:fopen();--->宽字符读取:wfsopen();
//注:二进制不涉及宽窄字符问题,但文本文件涉及到宽窄字符问题!
//08.根据文件进行加解密:携带密码
// 1.文件长度固定
// 2.根据r读取会少一些,\r\n-->\n导致明显少很多
// 解决方案:按照rb加解密-->否则就不会计算\r的长度
// 需要计算\r的长度
// 3.加密变大的原因:'A'-->'\n'[计算机]--->'\r\n'[存储之后]
// 少变多的原理:\n-->\r\n
//09.尤其是文本的加解密最复杂:
// 1.二进制的加解密最精确
// 2.某些情况下文本方式杜绝换行
// 3.密码加密:一段儿一段儿的进行加密动作(自适应处理)
//10.文本资源的加密解密:
// 文本文件加解密所需注意的事项
//11.注意事项:
// 1.文本加解密,所有字符单一加密方式,可以读写实现加密动作[读取一个加密一个]
// 2.文本文件按照密码加密,不能使用文本,防止\r\n问题的产生-->'A'-->'\n'-->'\r\n'
// 3.获取文件硬盘尺寸的时候尽量使用rb
// 4.读取字符的时候避免以外结束标记,就使用int接收单个字符
// 5.图片也可以进行加解密[二进制方式]
// 6.加解密:视频锁定,解密
///02.加解密二进制.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//01.标识符的作用域:
// C语言当中使用static关键字
//注:C语言防止标识符的作用域泄露问题使用static关键字
static char * pSrcPath = "D:\\TestSpace\\TestData\\周杰伦的微笑.jpg";
static char * pEnPath = "D:\\TestSpace\\TestData\\周杰伦的微笑En.jpg";
static char * pDePath = "D:\\TestSpace\\TestData\\周杰伦的微笑De.jpg";

//02.获取二进制文件硬盘尺寸:
// 根据二进制文件尺寸决定下一步操作
int getBinFileSize(char * pBinFile)
{
    FILE * pfr = fopen(pBinFile, "rb");
    if (NULL == pfr)
        return -1;
    //char chr = '\0';//截断现象
    int size = -1;
    //int chr = 0;//无论如何都不会产生阶段现象
    while (!feof(pfr))
    {
        fgetc(pfr);
        ++size;
    }
    return size;
}

//03.二进制通过密码实现加解密
// 1.固定尺寸遍历
// 2.手动重置特点
// 3.自动重置特点(最优化的方式)
//注:对每个字节都进行单独的加解密操作
// 效率低下+代码最简
void binEnDeCryptByPass(char * pSrcPath, char * pDesPath, char * pPassStr)
{
    FILE * pfr = fopen(pSrcPath, "rb");
    FILE * pfw = fopen(pDesPath, "wb");
    if (NULL == pfr || NULL == pfw)
        abort();
    int pPasLen = strlen(pPassStr);//获取密码长度,实现根据密码加密
    int i = 0;//0~len-1:按照数组正向环形队列的实现原理进行对len求模,回到原点,循环一直进行下去,环形队列定长特点
    //0 1 2 3//数组正向环形队列,循环一直进行下去的原理,数据存储原意,取余技巧
    //4 5 6 7//环状:头到尾-->尾到头
    //8 9 10 11//任何数值取余都是返回回至到0~3
    int chr = 0;
    while (EOF != (chr = fgetc(pfr)))
    {   //二进制读取+int接收=绝对的的文件结尾标识EOF
        //if (i == pPasLen)
        //{//手动回置
        // i = 0;
        //}
        int newChr = chr ^ pPassStr[i++ % pPasLen];//每个字符按照对应的位置进行异或运算[固定尺寸轮询方式]
        fputc(newChr, pfw);//自动回置
    }
    fclose(pfw);
    fclose(pfr);
}

int main03(void)
{
    printf("binFile.size = %d \n", getBinFileSize(pSrcPath));

    binEnDeCryptByPass(pSrcPath, pEnPath, "BingQiuChe");
    binEnDeCryptByPass(pEnPath, pDePath, "BingQiuChe");

    system("pause");
}



//01.在Windows操作系统当中:
// 回车符:
// 1.在从文本文件当中读取出来的时候为'\n',但是写入文本文件当中的时候却是'\r''\n'
// 2.因此含有'\r''\n'的文件在原始文件当中的大小比读取出来的大小大了一半儿[\r]
// Windows操作系统在写入文本文件当中的时候,只要识别到\r|\n就会将其
// 往文本文件当中写成'\r''\n'-->读取的时候,自动识别'\r''\n'-->\n[操作系统识别]
// 3.某些情况之下的文件加密操作会导致文件的大小变大或编写
// 就是在内存当中操作的时候,\n的增多还是减少[回车符在操作系统当中会被整体识别操作]
//02.加密&解密文件的时候会有微小的大小差距特点,因为回车符在存储的时候,会采取\r\n进行存储
// 然而读取的时候,操作系统自动将回车符\r\n整体识别,解析成为\n导致变小,大小减半,因为解析
// 的时候缺少了一个字符(因此文件加解密最好采用二进制方式)
//03.文本文件的数据加解密运算:
// 1.最复杂的待加密文件
// 2.加密方式:密码加密&非密码加密
//04.二进制文件加解密运算:
// 1.加解密同时进行-->按照单字节进行加密[无需密码]-->按照密码串加密[需要密码]
// 2.文件加密的第一步骤:获取文件的字节大小
// 3.任何二进制文件都可以进行加解密:
// 文本文件加密:文件相对于待加密文件会出现变大或者变小的情况
// 二进制文件加密:文本相对于待加密文件既不会出现变大也不会出现变小的情况
//05.隐藏木马偷偷执行的方式:
// 1.方式一:加密运算+方式二:修改扩展名[导致文件不能够正常进行解析]
// 2.木马还可以进行配置:生成客户端
// (1).文本内容读取-->堆内存-->配置信息-->客户端
// (2).无规律文件-->内存配置操作-->客户端

程序片段(05):切割与合并.c
内容概要:二进制文件的切割与合并

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

//01.[.exe]文件-->_1.exe&_2.exe&_3.exe[切割原理&分卷压缩]
// 文件分割:名称规律-->子文件的顺序合并规律
//02.切割文件的大小大多都是未知情况:
// 文件切割问题:流程
// 获取文件大小-->判断是否能够被子文件数目整除
// 生成文件指针数组-->存储各个子文件的磁盘路径
//03.3分块儿切割&合并路径特点&保证扩展名相同
//char path[1024] = "D:\\TestData\\Q.exe";
//D:\\TestData\\Q01.exe
//D:\\TestData\\Q02.exe
//D:\\TestData\\Q03.exe

//04.获取二进制文件字节尺寸
int getbinfilesize(char *path)
{
    FILE *pfr = fopen(path, "rb");
    if (pfr==NULL)
    {
        return -1;
    }
    else
    {
        fseek(pfr, 0, SEEK_END);//(1)指针移动到文件末尾:指针求取方式pfr+0+SEEK_END
        int size = ftell(pfr);//(2)获取当前指针距离文件开头的距离[系统自动识别pfr开始点]
        fclose(pfr);
        return size;
    }
}

//05.文件路径分割&文件数据分开存储
void divide(char *path, int num)
{//(1).分割为num个路径
    //(2).可写的字符串数组:文件指针数组
    char **pathes = NULL;//存储文件指针数组的指针
    pathes = malloc(sizeof(char *)*num);//(3).在堆内存当中开辟存储文件指针数组的空间
    for (int i = 0; i < num; i++)  
    {//(4).为每个文件指针指向的路径字符串数组开辟存储空间[存储路径字符串的数组]
        pathes[i] = malloc(sizeof(char) * 256);
        sprintf(pathes[i], "D:\\TestData\\Q%d.exe", i + 1);
        //printf("\n%s", pathes[i]);//测试路径
    }
    FILE *pfr = fopen(path, "rb");
    if (pfr==NULL)
    {
        return;
    }
    else
    {
        //100 10 10//(5).任意指定路径个数:举例说明
        //100 8 --->7*14=98...2;
        int size = getbinfilesize(path);
        if (size%num == 0)
        {//整除
            for (int i = 0; i < num; i++)
            {
                FILE *pfw = fopen(pathes[i], "wb");
                for (int j = 0; j < size / num; j++)
                {
                    fputc(fgetc(pfr), pfw);//(6).读取一个字节数据写入一个字节数据
                }
                fclose(pfw);
            }
        }
        else
        {//非整除
            for (int i = 0; i < num-1; i++)
            {
                FILE *pfw = fopen(pathes[i], "wb");
                for (int j = 0; j < size / (num - 1); j++)
                {//(7).分成num个文件就除以(num-1)-->类似于:100分为8个文件
                    //100&8-->100/(8-1)=7*14....2;-->100%(8-1)=2
                    fputc(fgetc(pfr), pfw);
                }
                fclose(pfw);
            }
            //(8).pfr的指针一直不断往前进行移动,不会自动重置到文件指针的开始位置
            {
                //目录个数:1 2 3 4 5--num个文件
                //索引对应:0 1 2 3 4-->最后一个目录4=5-1=num-1
                FILE *pfw = fopen(pathes[num - 1], "wb");//写入最后一个文件当中
                for (int i = 0; i < size % (num - 1); i++)
                {
                    fputc(fgetc(pfr), pfw);
                }
                fclose(pfw);
            }
        }
    }
    fclose(pfr);
}

//03.文件数据合并
void merge(char *path, int num)
{//(1).扫描指定目录,提取名称规律的数组
    char **pathes;
    pathes = malloc(sizeof(char*)*num);
    for (int i = 0; i < num; i++)
    {
        pathes[i] = malloc(sizeof(char) * 512);
        sprintf(pathes[i], "D:\\TestData\\Q%d.exe", i + 1);
    }
    FILE *pfw = fopen(path, "wb");
    for (int i = 0; i < num; i++)
    {//(2).逐个扫描文件数据
        int length = getbinfilesize(pathes[i]);
        if (length==-1)
        {
            return;
        }
        else
        {//(3).执行文件数据合并
            FILE *pfr = fopen(pathes[i], "rb");
            for (int j = 0; j < length; j++)
            {
                fputc(fgetc(pfr), pfw);
            }
            fclose(pfr);//(4).将数据从缓冲区当中强制刷入到指定文件当中
        }
    }
    fclose(pfw);//(5).结束最终合并操作
}

//文件切割与合并
void main01()
{
    //printf("%d", getbinfilesize(path));

    //divide("D:\\TestData\\Q.exe", 5);//(1)这里的文件切割可能存在一定的优化机制

    //merge("D:\\TestData\\QNew.exe", 5);

    system("pause");
}





//01.二进制文件的切割与加密:
// 文本文件不是很大-->加密看不错-->分散隐藏-->分割更加看不错
//02.文件操作:
// 二进制文件:
// 切割&合并--加解密
// 文本文件:
// 切割&合并--加解密
//03.文件分类:
// 图片文件.bmp&.jpg以及可执行文件.exe都是二进制文件,都可以以
// 二进制数据的方式进行操作-->二进制切割&合并
//04.文件的切割与合并:
// 1.二进制-->文本[要求变高:需要处理\n-->\r\n的关系]
// 2.单线程实现-->多线程实现[操作效率的明显提高]
//05.文件切割&合并原理:
// 1.和文件加密原理类似
// 2.分块儿进行存储,最后不足的一块儿分开进行处理
// 3.最后按照文件名称规律进行顺序合并-->文件名规律
//06.某些时候文件切割之后的子文件末尾会添加一个切割文件
// 之后的结尾符
//07.二进制文件的切割与合并原理:升级操作[多线程]
// 切割-->分段
// 合并-->合段

程序片段(06):01.fgets与fputs.c+02.数据排查.c+03.文本文件增删查改.c
内容概要:fgets与fputs

///01.fgets与fputs.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

 //fgets();&fputs();函数细节演示-->自定义缓冲区操作
void main01()
{//(1)打开一个文件-->转义字符处理[回车符]-->打开方式 
    FILE *pfr = fopen("D:\\TestData\\Test01.txt", "r");
    //(2)fgets();获取键盘录入的字符串&fputs();将字符串输出到显示器
    //fgets():的返回值是int类型[正常],NULL[出错,结尾符]
    //(3)将字符全部读取出来有两种方式:fgetc();&gets();
    while (!feof(pfr))
    {
        char str[256] = { 0 };//相当于自定义的一个缓冲区
        //(4)设为255的原因,最后一个无论如何都会被作为结尾符
        fgets(str, 255, pfr);//(5)读取一个字符串,是最长长度,文件指针[获取的是文本文件当中的整个字符串]
        printf("%s", str);
    }
    fclose(pfr);

    system("pause");
}

void main02()
{
    //fgets();读取-->fputs();写出
    FILE *pfr = fopen("D:\\TestData\\Test01.txt", "r");
    FILE *pfw = fopen("D:\\TestData\\Test01_R.txt", "w");
    //while (!feof(pfr))
    //{//(1)feof();是通用的文件结束判断方式[操作系统决定]
    // char str[256] = { 0 };//(2)缓冲区的大小决定了数据读取的次数
    // fgets(str, 255, pfr);//(2)fgets();没有到结尾的时候一直不断进行读取,而且知道自动以缓冲区装满为止[255说明一次性读取的字符个数]
    // fputs(str, pfw);//(3)fputs();用于将字符串写入到文件当中
    // //printf("%s", str);//(4)打印出来的时候是由格式的
    //}
    //fclose(pfr);
    //fclose(pfw);

    //fgetc();的返回值是int-->fgets();的返回值是char
    char str[256] = { 0 };
    while (fgets(str,255,pfr)!=NULL)
    {//(5)优化读取写入方式
        int length = fputs(str, pfw);
        //(6)遍历文件的三种方式:feof();&fgetc();fgets();
        //fgets();-->返回值:str|NULL
        //(7)fputs();的返回值是-->最后一次输出的字符:0
        //正常的时候返回写入的最后一个字符,出错返回EOF
        //0|EOF-->EOF在写满数据的时候才会出现
        printf("\n%d", length);//(8)fgets();按行进行字符串数据的扫描,知道直到扫描完成为止
    }
    fclose(pfr);
    fclose(pfw);
    system("D:\\TestData\\Test01_R.txt");

    system("pause");
}





//01.大数据相关数据:CSDN&DangDang&QQ数据
// "行"方式存储-->不等长-->账号+密码
//02.行读取方式:fgets();&fputs();
// 一次读取一行,过渡字符串缓冲区,最终全部进入
//03.实现数据的增删查改:
// 复制-->增删查改动作-->最终结果
//04.实战型案例:文本文件的切割
// fgets();&fputs();
//05.fgets();&fputs();的特点:
// 行读取-->\r\n结尾-->fgets();-->fputs();
// fgets();读取N-1个字符,指向内存缓冲区,并且在最后自动添加一个'\0'作为字符串结尾标识符
//06.异常数据排查
///02.数据排查.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//01数据排查演示
void main03()
{
    //(1)数据排查:分路径总结数据
    FILE *pfr = fopen("D:\\CSCSpace\\03DevelopTools\\03DB\\QQSmall.txt", "r");
    FILE *pfwgood = fopen("D:\\TestData\\QQSmallGood.txt", "w");
    FILE *pfwbad = fopen("D:\\TestData\\QQSmallBad.txt", "w");
    while (!feof(pfr))
    {
        char str[256] = { 0 };
        fgets(str, 255, pfr);
        int length = strlen(str);
        //(2)数据排查动作&垃圾数据[拷贝数据之前进行排除动作,内存操作]
        if (length>=50)
        {//(3)垃圾数据排除动作的执行位置[垃圾数据读取到一个文件,正常数据同样读取到另外一个文件,缓冲区操作,数据分类]
            //printf("%s", str);
            fputs(str, pfwbad);
        }
        else
        {//(4)数据筛选分类,手动查找筛选比较累
            //(5)异常数据排查的原因在于:防止数据操作错误[跳出指定规则的操作]
            //(6)开放数据-->CGI查询-->更加的商业化
            //(7)这里是一边儿进行读取,一边儿进行分离[这样不会过度占用内存]
            //内存缓冲区的概念:所有数据提取,可能有用,可能没用
            fputs(str, pfwgood);
        }
        //printf("%s", str);
    }

    system("pause");
}



//01.异常数据排除原理:
// 1.稳妥&避免异常-->使用长度为255,留出一个空位用于保存结尾符-->fgets();自动填充'\0'
// 2.异常数据排查-->长度不能超过50,排查动作,便于后期数据正常处理
//02.数据排查:
// 1.处理大数据的时候:加载数据进入内存,然后在内存当中进行数据的处理
// 2.内存当中进行数据处理,排查操作,增删改查动作
// 原理:符合条件&不符合条件-->文件分离&筛选
//03.增删改查某一段儿数据:
// 1.所有动作都在:加载进内存当中再进行数据处理[内存数据操作]
// 2.数据排查的是偶嵌套fgets();&fputs();操作方案
///03.文本文件增删查改.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//01数据行查询
void main04()
{
    //查询:
    FILE *pfr = fopen("D:\\TestData\\10.txt", "r");
    FILE *pfw = fopen("D:\\TestData\\Temp.txt", "w");
    while (!feof(pfr))
    {
        char str[128] = { 0 };
        fgets(str, 128, pfr);//读取
        char *p = strstr(str, "王鹏飞");
        if (p != NULL)
        {
            printf("%s", str);
        }
    }
    fclose(pfr);//(1)这里的操作是非缓冲区模式,需要进行必要的手动关闭动作
    fclose(pfw);

    system("pause");
}

//02数据行修改
void main05()
{
    //FILE *pfr = fopen("D:\\TestData\\10.txt", "r");
    //FILE *pfw = fopen("D:\\TestData\\Temp.txt", "w");
    //while (!feof(pfr))
    //{
    // char str[128] = { 0 };
    // fgets(str, 128, pfr);//读取
    // char *p = strstr(str, "王鹏飞");
    // if (p!=NULL)
    // {//(1)对数据执行多重操作
    // //printf("%s", str);
    // fputs("上联:六问赵学辉有多愁,下联:恰似跑堂杂役在青楼,横批:看别人射\n", pfw);
    // }
    // else
    // {
    // fputs(str, pfw);
    // }
    //}
    //fclose(pfr);
    //fclose(pfw);

    //(2)文件处理方式:remove();删除源文件&rename();重命名
    rename("D:\\TestData\\Temp.txt", "D:\\TestData\\HeHe.txt");
    remove("D:\\TestData\\HeHe.txt");

    system("pause");
}

//03数据行删除
void main06()
{
    FILE *pfr = fopen("D:\\TestData\\10.txt", "r");
    FILE *pfw = fopen("D:\\TestData\\Temp.txt", "w");
    while (!feof(pfr))
    {
        char str[128] = { 0 };
        fgets(str, 128, pfr);
        char *p = strstr(str, "赵学辉");
        if (p != NULL)
        {
            //printf("%s", str);
            //删除动作,不进行输出就行了
        }
        else
        {
            fputs(str, pfw);
        }
    }
    fclose(pfr);
    fclose(pfw);

    system("pause");
}

//04数据行增加
void main07()
{
    FILE *pfr = fopen("D:\\TestData\\10.txt", "r");
    FILE *pfw = fopen("D:\\TestData\\Temp.txt", "w");
    while (!feof(pfr))
    {
        char str[128] = { 0 };
        fgets(str, 127, pfr);
        char *p = strstr(str, "王鹏飞");
        if (p != NULL)
        {
            //(1)在这儿进行数据行前插与后插的控制
            //fputs("上联:十问赵学辉有多愁,下联:恰似一群凤姐上青楼,横批:只能用手\n", pfw);
            fputs(str, pfw);
            fputs("上联:二问中国男足有多愁,下联:恰似赵学辉守青楼,横批:总是被射\n", pfw);
        }
        else
        {
            fputs(str, pfw);
        }
    }
    fclose(pfr);
    fclose(pfw);

    system("pause");
}



//01.文本文件的增删改查:
// 1.思路:加载进内存-->在内存自定义缓冲区当中进行数据匹配-->修改|删除
// 2.原理:对一行一行的数据进行读取,找到所有需要进行修改的数据的时候
// 先不执行写入文件的动作,而是在早一行进行插入
// 3.最终:删除源文件,给新文件进行重新命名-->文件的增删改查
//02.替换原理:
// 将原始文件复制到新的文件当中
// 找到将要进行修改的数据就不写入新文件当中
// 写入新文件的时候采用替换字符串进行写入
//03.插入原理:
// 有前插与后插之分
//04.终极原理:在内存中对数据行进行操作

程序片段(07):01.数据加密.c+02.DangDang.c
内容概要:数据加密并查询

///01.数据加密.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h> 
#include <string.h>

//01单字符加密动作
void run01(char *str)
{//(1)加密采用同一个接口
    char *p = str;
    //(2)回车符处理机制-->指针的巧妙应用
    while (*p!='\0')
    {//(3)跳过回车符-->跳过处理-->文本文件
        if (*p == '\r' || *p == '\n')
        {
            *p = '\0';
        }
        p++;
    }
    int length = strlen(str);
    for (int i = 0; i < length; i++)
    {//(4)逐个遍历每个字符,进行异或加密方案
        str[i] ^= 3;//(5)单字节加密方案,容易操作文件字节数增大或减小[\n<-->\r\n特点]
    }
}

void main01()
{
    //(1)按照不同的模式打开一个文件并创建文件指针
    FILE *pfr = fopen("D:\\TestData\\10.txt", "r");
    FILE *pfw = fopen("D:\\TestData\\10temp.txt", "w");
    while (!feof(pfr))
    {//(2)读取一行数据再进行加密操作
        char str[1024] = { 0 };
        fgets(str, 1023, pfr);//(4)尾部必须是'\0',fgets();的默认操作
        run(str);//(5)加密
        fputs(str, pfw);
        //fputs('\n', pfw);//(6)加密之后的数据默认只是占用一行,所以不能使用fgets();进行操作,因为系统设定的内存缓冲区根本不够使用
    }
    fclose(pfr);
    fclose(pfw);

    system("pause");
}



//01.加密文件需要两个文件指针:
// 指针1读取数据-->加解密动作-->指针2写入数据
//02.加密之后的数据,默认只是占用一行:
// 所以在此操作加密数据的时候,不能够直接使用fgets();-->系统默认设定的内存缓冲区不够使用
//03.读取的时候只能一行一行的进行加密,不能够整体进行加密
//04.缓冲区概念:磁盘寿命的联系
// 缓冲区装满的时候自动执行数据刷出动作,fclose();函数是手动强制将内存缓冲区当中的数据刷出到指定的文件当中
///02.DangDang.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//01.单字符加密
void run(char *str)
{
    char *p = str;
    while (*p != '\0')
    {
        if (*p == '\r' || *p == '\n')
        {//回车符处理
            *p = '\0';
        }
        p++;
    }
    int length = strlen(str);
    for (int i = 0; i < length; i++)
    {//逐个字符加密
        str[i] ^= 3;
    }
}

//自定义内存数据缓冲区实现文件检索功能
void main02()
{
    FILE *pfr = fopen("D:\\TestData\\DataBase\\KaiFang.txt", "r");
    while (!feof(pfr))
    {
        char str[1024] = { 0 };
        fgets(str, 1024, pfr);
        //run(str);
        char *p1 = strstr(str, "陈友泽,");//(1)逗号分隔,提高字符扫描的精确度
        char *p2 = strstr(str, "四川");//(2)再次提高精确度
        if (p1 != NULL&&p2 != NULL)
        {//(3)搜索动作
            printf("%s\n", p1);
        }
    }
    fclose(pfr);

    system("pause");
}

void main()
{
    FILE *pfr = fopen("D:\\TestData\\DataBase\\1EQQBig.txt", "r");
    while (!feof(pfr))
    {
        char str[1024] = { 0 };
        fgets(str, 1023, pfr);
        //run(str);
        char *p1 = strstr(str, "897998246");
        //char *p2 = strstr(str, "蒙古");
        if (p1 != NULL/*&&p2 != NULL*/)
        {
            printf("%s\n", p1);
        }
    }
    fclose(pfr);

    system("pause");
}



//01.两GB的数据:数据加密
// 文本数据-->加密:按行进行加解密动作-->读取的时候按行进行读取,写入的时候按行进行写入
// -->解密:一行一行的读取到内存中,再进行细节的操作
//02.加密动作:
// 搜索功能的实现
//03.DangDang数据处理:
// 1.数据加密并查询
// 2.加密-->解密-->查询
//04.查询数据的两种模式:
// 磁盘模式&内存模式
// 磁盘模式-->内存模式
// 磁盘模式采用"自定义缓冲区"编程方式-->内存模式采用"内存数据库"操作方式

程序片段(08):Fseek.c
内容概要:fseek

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

//01显示文件指针结构体的信息
void showp(FILE *p)
{//(1)显示文件指针相关信息
    printf("\n\n"); //(2)每个文件指针都是指向一片儿内存缓冲区
    printf("\n缓冲区的有效数据%d", p->_cnt);
    printf("\n缓冲区的指针%p", p->_ptr);
    printf("\n缓冲区的起始地址%p", p->_base);
    printf("\n缓冲区的大小%d", p->_bufsiz);
    printf("\n缓冲区的文件描述符%d", p->_file);
}

//测试文件指针的信息
void main01()
{
    //showp(stdin);
    //char x;
    //x=getchar();
    //(1)a+回车符等同于两个字符
    //(2)这里会清空缓冲区内容
    //(3)a打印出来之后还剩下1个
    // 回车打印出来之后还剩下1个
    // 数据是一个个的进行提取,提取一个就少一个
    //putchar(x);
    //showp(stdin);
    //x = getchar();
    //putchar(x);
    //showp(stdin);
    //x = getchar();
    //showp(stdin);
    //(4)fflush();函数用于清空文件指针所指向的内存缓冲区
    //fflush(stdin);
    //showp(stdin);

    char path[150] = "D:\\TestData\\1.txt";
    FILE *pf = fopen(path, "r");
    while (!feof(pf))
    {//(5)由于这里预先读取了一个字符,所以剩余字符总是缺少了一个
        char ch = fgetc(pf);        
        showp(pf);
    }
    fclose(pf);

    system("pause");
}


void main()
{
    char path[150] = "D:\\TestData\\1.txt";
    FILE *pf = fopen(path, "a+");//(1)尾部追加动作,a+:尾部追加,因为文件指针最终就在文件内存缓冲区的末尾
                                 //FILE *pf = fopen(path, "r+");
                                 //FILE *pf = fopen(path, "w+");
                                 //FILE *pf = fopen(path, "r+");
                                 //(2)w+:首部覆盖,文件指针在头部,并且会进行内容的情况[先清空,再写入]
                                 //(3)r+:只会覆盖相同大小的位置,文件指针在头部,不会清空原始的内容[有内容,直接覆盖,覆盖不完的数据保留]
                                 //文件指针移动:尾部向前移动10个位置
    fseek(pf, 0, SEEK_END);//(4)a+模式下的文件指针移动无效,因为a+模式默认操作的指针位置就在文件指针所指向的内存缓冲区末尾
                           //r+:非清空动作的指定直接大小的位置覆盖,从头开始进行内容覆盖
                           //w+:先进行清空内容的动作
                           //(5)插入操作的实现:
    fputs("00000000", pf);//(6)拓展内存:这里的a+模式下的fputs();操作相当于拓展内存的特点-->尾部+追加
    fflush(pf);//(7)将文件指针缓冲区当中的内容刷出缓冲区
    int length = 10;
    //(8)反复移动指针
    for (int i = 0; i < 10; i++)
    {
        //1 2 3 4 5 6 7 8 9 10 EOF
        //0 1 2 3 4 5 6 7 8 9 0-->9-7-0-1=-8
        fseek(pf, -7 - i - 1, SEEK_END);//(9)一直都是-10的位置
        int ch = fgetc(pf);
        fseek(pf, -i, SEEK_END);//(10)长度自动发生变化
        fputc(ch, pf);
        fflush(pf);
    }
    fputs("abcdefg", pf);
    fclose(pf);
    system("D:\\TestData\\1.txt");

    system("pause");
}


//01.Fseek函数:
// 1.跳到指定的文件指针,再做一系列的操作
// 2.随意移动文件指针的作用,让文件指针在内存文件缓冲区的任意位置
//02.文本文档:
// 1.1234567890a1234577890b1234567890c1234567890d
// 2.要求:只想读取后面10个字符或者前面10个字符
//03.文件指针在内存缓冲区当中随意的进行移动
// 任意读取任何位置的字符[随机读取]
//04.文件指针信息:
// 1.FILE文件类型的本质就是一个结构体-->结构体封装文件的描述信息
// 2.如何显示一个文件指针的所有信息?
// 3.fgets();&fputs();操作的都是缓冲区,而非硬盘[内存缓冲区操作]
// 所以这儿可以通过移动缓冲区的指针,读取任意的内容
//05.缓冲区特点:缓冲区操作-->操作文件
// 1.缓冲区指针不断的往前进行移动
// 2.缓冲区的开始地址不会发生变化
// 3.文件指针操作的位置-->随机进行读写操作
// 4.手动控制内存缓冲区的大小(提升读写效率)
//06.对一个文件同时进行读写操作:
// 参数:r+/rb+||w+/wb+||a+/ab+[追加的状态之下,同时进行读写操作]
//07.随机读写就需要操作文件指针的位置

你可能感兴趣的:(CCPP)