-
2021-01-03 10:22:12
用C++简单实现了文件管理系统
1.菜单展示,供用户选择
2.简单打开文件,写入数据操作
3.读取文件内容操作
4.清空文件操作
5.退出管理系统
主函数:实现算法框架#include<iostream>//标准输入输出流头文件 using namespace std;//标准命名空间 #include"fileManager.h" int main() { int choice = 0;//用于存储用户输入 fileManager fm; while(true) { fm.show_Menu(); cout << "请输入您的选择:" << endl; cin >> choice; switch(choice) { case 1://打开文件并写入数据 fm.open_file(); break; case 2://查看文件内容 fm.show_file(); break; case 3://清空文件内容 fm.clear_file(); break; case 0://退出 fm.exit_system(); break; default: system("cls");//清屏 break; } } system("pause"); return 0; }
fileManager.h头文件:实现文件管理的简单声明
#pragma once//防止头文件包含 #include<iostream>//标准输入输出流头文件 using namespace std;//标准命名空间 #include<string> //设计文件管理类 class fileManager { public: //展示菜单 void show_Menu(); //打开文件 void open_file(); //查看文件 void show_file(); //清空文件 void clear_file(); //退出系统 void exit_system(); };
fileManager.cpp源文件,fileManager.h中的函数实现
#include"fileManager.h" #include<fstream>//文件操作头文件 //菜单功能 void fileManager::show_Menu() { cout << "********************************" << endl; cout << "******* 1.打开文件并写入数据 *******" << endl; cout << "******* 2.查看文件内容 *******" << endl; cout << "******* 3.清空文件内容 *******" << endl; cout << "******* 0.退出 *******" << endl; cout << "********************************" << endl; } //打开文件并写入数据 void fileManager::open_file() { ofstream ofs;//输出文件流对象 csv格式所有数据都用逗号进行分割 ofs.open("data.csv",ios::out | ios::app);//用追加方式写文件 int numble = 0; cout << "请输入您本次想保存一个数据:" << endl; cin >> numble; ofs << numble << "," ; cout << "本次记录已保存!" << endl; system("pause");//按任意键继续 system("cls");//清屏 } //查看文件 void fileManager::show_file() { ifstream ifs("data.csv",ios::in);//读文件 //文件不存在时 if(!ifs.is_open()) { cout << "文件不存在" << endl; ifs.close(); return; } //文件清空情况 char ch; ifs >> ch; if(ifs.eof()) { cout << "文件为空" << endl; ifs.close(); return; } //文件不为空时 ifs.putback(ch);//将上面读取的单个字符放回来 string num; while(!ifs.eof())//eof函数判断是否读到文件结尾 {//按行读取文件中信息 getline(ifs,num);//str用来储存ifs输入流中的信息 cout << num << endl;//将读取到的信息输出到屏幕上 } ifs.close(); system("pause"); system("cls"); } //清空文件 void fileManager::clear_file() { cout << "确认清空?1、确认 2、返回" << endl; int select = 0; cin >> select; if(select == 1) { ofstream ofs("data.csv",ios::trunc); ofs.close(); cout << "清空成功!" << endl; } system("pause"); system("cls"); } //退出系统 void fileManager::exit_system() { cout << "欢迎下次使用" << endl; system("pause"); exit(0); }
小白学习中,欢迎交流指正!
更多相关内容 -
C++实现多目录文件系统
2015-04-15 21:30:31C++实现多目录文件系统,其中代码很用心的编写。可以通过。 -
c++实现文件的加密和解密
2018-10-15 17:10:08VS2008实现c++对文件进行加密和解密操作,加密之后文件只会显示乱码,解码之后正常显示 -
c++钩子技术实现文件监控
2019-01-24 19:53:22利用钩子技术实现特定文件的增删改的监控,隐式调用钩子 -
删除文件恢复C++实现
2018-05-27 17:27:38windows操作系统下,C++编写实现对ntfs及fat32文件系统中被删除文件的恢复。 -
c++ 实现 http 协议 上传下载文件
2020-04-02 20:52:56c++ 实现,在 linux 平台测试通过,windows 上原理是一样的,下载上传大文件没有问题, -
C/C++仿真实现Linux文件系统
2016-02-23 23:19:33C/C++仿真实现Linux文件系统,主要有文件管理、文件操作、用户管理、文件共享等功能 -
C/C++实现FAT文件系统的读写
2009-09-28 16:28:47不用windows接口实现FAT文件系统的文件信息 -
c++实现的十分简易文件系统
2017-06-27 16:31:17本系统已经实现的相关操作: 所有操作都不支持从根目录索引,即都只能访问当前目录下的文件,不能用/a/b越级访问 1)目录相关操作 列出目录下所有文件:ls 切换目录:cd newdir 显示目录:pwd 创建目录:mkdir ...课题作业任务:在内存中开辟一个100M的空间作为磁盘空间,在此上模拟创建一个文件管理系统。
本系统已经实现的相关操作:
所有操作都不支持从根目录索引,即都只能访问当前目录下的文件,不能用/a/b越级访问
1)目录相关操作
列出目录下所有文件:ls
切换目录:cd newdir
显示目录:pwd
创建目录:mkdir dirName
删除目录和目录下所有文件:rmdir dirName
修改目录名或文件名:mv oldName newName
2)文件相关操作
创建文件(大小以1KB为单位):touch filename fileSize
删除文件:rm filename
从上一次后读取size字节的文件内容:read fileName size
从头开始读取size字节的文件内容:reread fileName size
从文件尾写入内容:write fileName content
清空文件,从头写入:rewrite fileName content
3)系统操作
使用命令帮助:help
退出系统:quit
全部代码大概有600多行,是一个非常简单的实现,不适合想要深入了解的人观看,网上有其他的功能较为强大实现,代码都在上千,比较具有学习的价值。
点击打开链接(很强大,我自己也还没有仔细看)
点击打开链接(代码好像有点问题)
1. 系统层次结构:
系统接口:是该文件系统提供给用户可以使用的命令接口,如ls,mkdir,touch等
文件管理:是系统对于文件和目录层次的管理的,规定了FCB结构,目录结构等,包含了对接口的实现。
磁盘管理:是系统最底层直接对内存空间的管理,如磁盘空闲空间管理,磁盘空间的分配方式等。
2. 磁盘管理
盘块大小:以1KB的空间作为系统盘块,用以分配的基本单位
分配方式:系统采用连续分配的方式,在磁盘上划定要求的连续盘块分配给文件使用
空间管理:系统采用位示图的方法,标记了磁盘上所有盘块的使用情况。
使用systemStartAddr标记了整个系统的起始地址,以1KB作为盘块划分,所以本系统共有100K个盘块。位示图用char[]表示,所以位示图大小为100KB。位示图存储在系统起始位置,在系统初始化时,0~99号盘块默认被存储位示图使用。
磁盘向文件管理提供的接口说明:
DiskOperate.h#ifndef DISKOPERATE_H_INCLUDED #define DISKOPERATE_H_INCLUDED //磁盘操作接口 #define system_size 100*1024*1024 //系统大小 #define block_szie 1024 //盘块大小 #define block_count system_size/block_szie //系统盘块数目 //初始化系统 void initSystem(); //磁盘分配 int getBlock(int blockSize) ; //获得盘块的物理地址 char* getBlockAddr(int blockNum); //获得物理地址的盘块号 int getAddrBlock(char* addr); //释放盘块、 int releaseBlock(int blockNum, int blockSize); //退出系统 void exitSystem(); #endif // DISKOPERATE_H_INCLUDED
3.文件层次管理说明
FileOperate.h (部分内容)//目录项结构: struct dirUnit{ char fileName[59]; //文件名 char type; //文件类型,0目录, 1文件 int startBlock; //FCB起始盘块 }; //一个目录项包含了文件名和文件类型,当文件为目录时,起始盘块指示了目录表所在的盘块号,当文件为文件时,起始盘块指示了FCB所在的盘块号。 #define dirTable_max_size 15 //目录表项最大值 //目录表结构: struct dirTable { int dirUnitAmount;//目录项数目 dirUnit dirs[dirTable_max_size];//目录项列表 }; /* 本系统规定一个目录表只占用一个盘块,一个目录项大小为64B,所以一个目录表中最多可含15个目录项,dirUnitAmount记录每个目录表中已含有的目录项数目。系统在初始化时,会自动生成一个空的根目录表存放于磁盘中,作为用户的初始位置,用户所有的目录和文件都这个表为根进行树状目录结构的展开。 当创建一个目录表时,系统会自动为目录表加上一项名为”..”的目录项,指示父目录表的位置。 */ //FCB结构: struct FCB { int blockNum; //文件数据起始盘块号 int fileSize; //文件大小,盘块为单位 int dataSize; //已写入的内容大小,字节为单位 int readptr; //读指针,字节为单位 int link; //文件链接数 }; /* 文件控制块包含了文件数据的起始位置和大小。dataSize,readptr是为文件的读写操作而准备的,记录文件已写入的内容长度(不可超过文件大小),和当前读取的位置。Link记录了文件的链接数,用于文件的共享,当文件的链接数为0时,系统可以回收文件的空间。同样的,一个FCB大小为20B,但也用一个盘块保存。 由于采用的是连续分配方式,所以系统规定文件被创建时,必须给出文件的大小,而且后期也不能修改文件的大小。 */
看到这里,如果你有修过计算机系统的话,你就会发现我采取了一种最简单的实现方式,都说了十分简易嘛~~
系统用char[]数组作为位示图保存了每一个盘块的使用状态,而且采取了连续分配的方式,对于目录表和FCB都规定直接使用一个盘块,文件又是规定好大小不能扩展的,所以实现起来减少了很多FAT,索引表,那些离散分配所需的连接方式,单纯练手的话,还是十分简易的。
具体实现
1. 磁盘管理的实现
这部分比较简单,代码备注也很详细了,可以直接看代码
DiskOperate.cpp
#include"DiskOperate.h" #include<stdio.h> #include<stdlib.h> char* systemStartAddr; //系统起始地址 //初始化系统 void initSystem() { //创建空间 systemStartAddr = (char*)malloc(system_size * sizeof(char)); //初始化盘块的位示图 for(int i=0; i<block_count; i++) systemStartAddr[i] = '0'; //用于存放位示图的空间已被占用 int bitMapSize = block_count * sizeof(char) / block_szie;//位示图占用盘块数:100 for(int i=0; i<bitMapSize; i++)//从零开始分配 systemStartAddr[i] = '1'; //盘块已被使用 } //退出系统 void exitSystem() { free(systemStartAddr); } //磁盘分配 int getBlock(int blockSize) { int startBlock = 0; int sum=0; for(int i=0; i<block_count; i++) { if(systemStartAddr[i] == '0')//可用盘块 { if(sum == 0)//刚开始,设置开始盘块号 startBlock = i; sum++; if(sum == blockSize)//连续盘块是否满足需求 { //满足分配,置1 for(int j=startBlock; j<startBlock+blockSize; j++) systemStartAddr[j] = '1'; return startBlock; } } else//已被使用,连续已经被打断 sum = 0; } printf("not found such series memory Or memory is full\n"); return -1; } //获得盘块的物理地址 char* getBlockAddr(int blockNum) { return systemStartAddr + blockNum * block_szie; //偏移量单位为字节 } //获得物理地址的盘块号 int getAddrBlock(char* addr) { return (addr - systemStartAddr)/block_szie; } //释放盘块、 int releaseBlock(int blockNum, int blockSize) { int endBlock = blockNum + blockSize; //修改位示图盘块的位置为0 for(int i=blockNum; i<endBlock; i++) systemStartAddr[i] = '0'; return 0; }
2.文件管理
首先说明全局变量
结构体定义可以见上面文件管理dirTable* rootDirTable; //根目录 dirTable* currentDirTable; //当前所在目录位置 char path[200]; //保存当前绝对路径
1)创建文件:touch fileName size
创建文件的过程可以为:
为文件控制块申请空间->为文件数据申请空间->创建FCB控制块->在当前目录添加相关的目录项描述
//创建文件 int creatFile(char fileName[], int fileSize) { //检测文件名字长度 if(strlen(fileName) >= 59) { printf("file name too long\n"); return -1; } //获得FCB的空间 int FCBBlock = getBlock(1); if(FCBBlock == -1) return -1; //获取文件数据空间 int FileBlock = getBlock(fileSize); if(FileBlock == -1) return -1; //创建FCB if(creatFCB(FCBBlock, FileBlock, fileSize) == -1) return -1; //添加到目录项 if(addDirUnit(currentDirTable, fileName, 1, FCBBlock) == -1) return -1; return 0; } //创建FCB int creatFCB(int fcbBlockNum, int fileBlockNum, int fileSize) { //找到fcb的存储位置 FCB* currentFCB = (FCB*) getBlockAddr(fcbBlockNum); currentFCB->blockNum = fileBlockNum;//文件数据起始位置 currentFCB->fileSize = fileSize;//文件大小 currentFCB->link = 1;//文件链接数 currentFCB->dataSize = 0;//文件已写入数据长度 currentFCB->readptr = 0;//文件读指针 return 0; } //添加目录项 int addDirUnit(dirTable* myDirTable, char fileName[], int type, int FCBBlockNum) { //获得目录表 int dirUnitAmount = myDirTable->dirUnitAmount; //检测目录表示是否已满 if(dirUnitAmount == dirTable_max_size) { printf("dirTables is full, try to delete some file\n"); return -1; } //是否存在同名文件 if(findUnitInTable(myDirTable, fileName) != -1) { printf("file already exist\n"); return -1; } //构建新目录项 dirUnit* newDirUnit = &myDirTable->dirs[dirUnitAmount]; myDirTable->dirUnitAmount++;//当前目录表的目录项数量+1 //设置新目录项内容 strcpy(newDirUnit->fileName, fileName); newDirUnit->type = type; newDirUnit->startBlock = FCBBlockNum; return 0; } //从目录中查找目录项目 int findUnitInTable(dirTable* myDirTable, char unitName[]) { //获得目录表 int dirUnitAmount = myDirTable->dirUnitAmount; int unitIndex = -1; for(int i=0; i<dirUnitAmount; i++)//查找目录项位置 if(strcmp(unitName, myDirTable->dirs[i].fileName) == 0) unitIndex = i; return unitIndex; }
2)删除文件:rm fileName
删除文件的流程可以分为:
查找文件在当前目录的目录项描述内容->得到FCB的描述内容->释放FCB空间和文件数据空间->从目录表中删除文件的目录项
(也就是说,在这里其实只是把用户能得到文件的索引删除,而文件的内容在没有被覆盖之前依旧是存在的)
//删除文件 int deleteFile(char fileName[]) { //忽略系统的自动创建的父目录 if(strcmp(fileName, "..") == 0) { printf("can't delete ..\n"); return -1; } //查找文件的目录项位置 int unitIndex = findUnitInTable(currentDirTable, fileName); if(unitIndex == -1) { printf("file not found\n"); return -1; } dirUnit myUnit = currentDirTable->dirs[unitIndex]; //判断类型 if(myUnit.type == 0)//目录 { printf("not a file\n"); return -1; } int FCBBlock = myUnit.startBlock; //释放内存 releaseFile(FCBBlock); //从目录表中剔除 deleteDirUnit(currentDirTable, unitIndex); return 0; } //释放文件内存 int releaseFile(int FCBBlock) { FCB* myFCB = (FCB*)getBlockAddr(FCBBlock); myFCB->link--; //链接数减一 //无链接,删除文件 if(myFCB->link == 0) { //释放文件的数据空间 releaseBlock(myFCB->blockNum, myFCB->fileSize); } //释放FCB的空间 releaseBlock(FCBBlock, 1); return 0; } //删除目录项 int deleteDirUnit(dirTable* myDirTable, int unitIndex) { //迁移覆盖 int dirUnitAmount = myDirTable->dirUnitAmount; for(int i=unitIndex; i<dirUnitAmount-1; i++) { myDirTable->dirs[i] = myDirTable->dirs[i+1]; } myDirTable->dirUnitAmount--; return 0; }
3)目录的删除和创建
目录的创建和删除与文件的操作大致相同,创建目录时,目录表项的startBlock不是FCB而是指目录的存放位置,而且还要自动为其添加多一个父目录项“..”,用于跳转。删除目录时需要注意是否递归删除目录下的所有文件和目录。详请看最后的完整代码,这里不专门复述。
4)切换目录: cd dirName
cd指令,主要就是让当前目录currentDirTable指向新的目录盘块地址就可以了,目录盘块地址可以在当前目录表的表项中找到。
//切换目录 int changeDir(char dirName[]) { //目录项在目录位置 int unitIndex = findUnitInTable(currentDirTable, dirName); //不存在 if(unitIndex == -1) { printf("file not found\n"); return -1; } if(currentDirTable->dirs[unitIndex].type == 1) { printf("not a dir\n"); return -1; } //修改当前目录 int dirBlock = currentDirTable->dirs[unitIndex].startBlock; currentDirTable = (dirTable*)getBlockAddr(dirBlock); //修改全局绝对路径path if(strcmp(dirName, "..") == 0) { //回退绝对路径 int len = strlen(path); for(int i=len-2;i>=0;i--) if(path[i] == '\\') { path[i+1]='\0'; break; } }else { strcat(path, dirName); strcat(path, "\\"); } return 0; }
5)读文件:read fileName size主要就是获得文件的初始地址,然后根据需要的读取长度size和当前的读指针进行输出,如果遇到文件尾则输出#,读写的单位都是字节
reread就是先把读指针readptr置为0,然后执行读操作。//读文件 read int read(char fileName[], int length) { int unitIndex = findUnitInTable(currentDirTable, fileName); if(unitIndex == -1) { printf("file no found\n"); return -1; } //控制块 int FCBBlock = currentDirTable->dirs[unitIndex].startBlock; FCB* myFCB = (FCB*)getBlockAddr(FCBBlock); doRead(myFCB, length); return 0; } //执行读操作 int doRead(FCB* myFCB, int length) { //读数据 int dataSize = myFCB->dataSize; char* data = (char*)getBlockAddr(myFCB->blockNum); //在不超出数据长度下,读取指定长度的数据 for(int i=0; i<length && myFCB->readptr < dataSize; i++, myFCB->readptr++) { printf("%c", *(data+myFCB->readptr)); } if(myFCB->readptr == dataSize)//读到文件末尾用#表示 printf("#"); //换行美观 printf("\n"); return 0; }
6)写文件操作:write fileName content
和读文件差不多,不过是根据当前文件的数据长度,在文件末尾给文件以字节的形式赋值上输入的content内容,数据长度不能超过文件长度
//写文件,从末尾写入 write int write(char fileName[], char content[]) { int unitIndex = findUnitInTable(currentDirTable, fileName); if(unitIndex == -1) { printf("file no found\n"); return -1; } //控制块 int FCBBlock = currentDirTable->dirs[unitIndex].startBlock; FCB* myFCB = (FCB*)getBlockAddr(FCBBlock); doWrite(myFCB, content); return 0; } //执行写操作 int doWrite(FCB* myFCB, char content[]) { int contentLen = strlen(content); int fileSize = myFCB->fileSize * block_szie; char* data = (char*)getBlockAddr(myFCB->blockNum); //在不超出文件的大小的范围内写入 for(int i=0; i<contentLen && myFCB->dataSize<fileSize; i++, myFCB->dataSize++) { *(data+myFCB->dataSize) = content[i]; } if(myFCB->dataSize == fileSize) printf("file is full,can't write in\n"); return 0; }
7)展示目录下所有文件:ls对目录表进行遍历,同时根据文件类型做出不同的输出就可以了
//展示当前目录 ls void showDir() { int unitAmount = currentDirTable->dirUnitAmount; printf("total:%d\n", unitAmount); printf("name\ttype\tsize\tFCB\tdataStartBlock\n"); //遍历所有表项 for(int i=0; i<unitAmount; i++) { //获取目录项 dirUnit unitTemp = currentDirTable->dirs[i]; printf("%s\t%d\t", unitTemp.fileName, unitTemp.type); //该表项是文件,继续输出大小和起始盘块号 if(unitTemp.type == 1) { int FCBBlock = unitTemp.startBlock; FCB* fileFCB = (FCB*)getBlockAddr(FCBBlock); printf("%d\t%d\t%d\n", fileFCB->fileSize, FCBBlock, fileFCB->blockNum); }else{ int dirBlock = unitTemp.startBlock; dirTable* myTable = (dirTable*)getBlockAddr(dirBlock); printf("%d\t%d\n",myTable->dirUnitAmount, unitTemp.startBlock); } } }
8)FileOperate.cpp
几乎全部的内容都在上面做了阐述了
#include"FileOperate.h" #include<string.h> #include<stdio.h> dirTable* rootDirTable; //根目录 dirTable* currentDirTable; //当前位置 char path[200]; //保存当前绝对路径 //初始化根目录 void initRootDir() { //分配一个盘块空间给rootDirTable int startBlock = getBlock(1); if(startBlock == -1) return; rootDirTable = (dirTable*)getBlockAddr(startBlock); rootDirTable->dirUnitAmount = 0; //将自身作为父级目录 //addDirUnit(rootDirTable, "..", 0, startBlock); currentDirTable = rootDirTable; //初始化初始绝对路径 path[0]='\\'; path[1]='\0'; } //获得绝对路径 char* getPath() { return path; } //展示当前目录 ls void showDir() { int unitAmount = currentDirTable->dirUnitAmount; printf("total:%d\n", unitAmount); printf("name\ttype\tsize\tFCB\tdataStartBlock\n"); //遍历所有表项 for(int i=0; i<unitAmount; i++) { //获取目录项 dirUnit unitTemp = currentDirTable->dirs[i]; printf("%s\t%d\t", unitTemp.fileName, unitTemp.type); //该表项是文件,继续输出大小和起始盘块号 if(unitTemp.type == 1) { int FCBBlock = unitTemp.startBlock; FCB* fileFCB = (FCB*)getBlockAddr(FCBBlock); printf("%d\t%d\t%d\n", fileFCB->fileSize, FCBBlock, fileFCB->blockNum); }else{ int dirBlock = unitTemp.startBlock; dirTable* myTable = (dirTable*)getBlockAddr(dirBlock); printf("%d\t%d\n",myTable->dirUnitAmount, unitTemp.startBlock); } } } //切换目录 cd int changeDir(char dirName[]) { //目录项在目录位置 int unitIndex = findUnitInTable(currentDirTable, dirName); //不存在 if(unitIndex == -1) { printf("file not found\n"); return -1; } if(currentDirTable->dirs[unitIndex].type == 1) { printf("not a dir\n"); return -1; } //修改当前目录 int dirBlock = currentDirTable->dirs[unitIndex].startBlock; currentDirTable = (dirTable*)getBlockAddr(dirBlock); //修改全局绝对路径 if(strcmp(dirName, "..") == 0) { //回退绝对路径 int len = strlen(path); for(int i=len-2;i>=0;i--) if(path[i] == '\\') { path[i+1]='\0'; break; } }else { strcat(path, dirName); strcat(path, "\\"); } return 0; } //修改文件名或者目录名 mv int changeName(char oldName[], char newName[]) { int unitIndex = findUnitInTable(currentDirTable, oldName); if(unitIndex == -1) { printf("file not found\n"); return -1; } strcpy(currentDirTable->dirs[unitIndex].fileName, newName); return 0; } //******************创建和删除文件 //创建文件 touch int creatFile(char fileName[], int fileSize) { //检测文件名字长度 if(strlen(fileName) >= 59) { printf("file name too long\n"); return -1; } //获得FCB的空间 int FCBBlock = getBlock(1); if(FCBBlock == -1) return -1; //获取文件数据空间 int FileBlock = getBlock(fileSize); if(FileBlock == -1) return -1; //创建FCB if(creatFCB(FCBBlock, FileBlock, fileSize) == -1) return -1; //添加到目录项 if(addDirUnit(currentDirTable, fileName, 1, FCBBlock) == -1) return -1; return 0; } //创建目录 mkdir int creatDir(char dirName[]) { if(strlen(dirName) >= 59) { printf("file name too long\n"); return -1; } //为目录表分配空间 int dirBlock = getBlock(1); if(dirBlock == -1) return -1; //将目录作为目录项添加到当前目录 if(addDirUnit(currentDirTable, dirName, 0, dirBlock) == -1) return -1; //为新建的目录添加一个到父目录的目录项 dirTable* newTable = (dirTable*)getBlockAddr(dirBlock); newTable->dirUnitAmount = 0; char parent[] = ".."; if(addDirUnit(newTable, parent, 0, getAddrBlock((char*)currentDirTable)) == -1) return -1; return 0; } //创建FCB int creatFCB(int fcbBlockNum, int fileBlockNum, int fileSize) { //找到fcb的存储位置 FCB* currentFCB = (FCB*) getBlockAddr(fcbBlockNum); currentFCB->blockNum = fileBlockNum;//文件数据起始位置 currentFCB->fileSize = fileSize;//文件大小 currentFCB->link = 1;//文件链接数 currentFCB->dataSize = 0;//文件已写入数据长度 currentFCB->readptr = 0;//文件读指针 return 0; } //添加目录项 int addDirUnit(dirTable* myDirTable, char fileName[], int type, int FCBBlockNum) { //获得目录表 int dirUnitAmount = myDirTable->dirUnitAmount; //检测目录表示是否已满 if(dirUnitAmount == dirTable_max_size) { printf("dirTables is full, try to delete some file\n"); return -1; } //是否存在同名文件 if(findUnitInTable(myDirTable, fileName) != -1) { printf("file already exist\n"); return -1; } //构建新目录项 dirUnit* newDirUnit = &myDirTable->dirs[dirUnitAmount]; myDirTable->dirUnitAmount++;//当前目录表的目录项数量+1 //设置新目录项内容 strcpy(newDirUnit->fileName, fileName); newDirUnit->type = type; newDirUnit->startBlock = FCBBlockNum; return 0; } //删除文件 rm int deleteFile(char fileName[]) { //忽略系统的自动创建的父目录 if(strcmp(fileName, "..") == 0) { printf("can't delete ..\n"); return -1; } //查找文件的目录项位置 int unitIndex = findUnitInTable(currentDirTable, fileName); if(unitIndex == -1) { printf("file not found\n"); return -1; } dirUnit myUnit = currentDirTable->dirs[unitIndex]; //判断类型 if(myUnit.type == 0)//目录 { printf("not a file\n"); return -1; } int FCBBlock = myUnit.startBlock; //释放内存 releaseFile(FCBBlock); //从目录表中剔除 deleteDirUnit(currentDirTable, unitIndex); return 0; } //释放文件内存 int releaseFile(int FCBBlock) { FCB* myFCB = (FCB*)getBlockAddr(FCBBlock); myFCB->link--; //链接数减一 //无链接,删除文件 if(myFCB->link == 0) { //释放文件的数据空间 releaseBlock(myFCB->blockNum, myFCB->fileSize); } //释放FCB的空间 releaseBlock(FCBBlock, 1); return 0; } //删除目录项 int deleteDirUnit(dirTable* myDirTable, int unitIndex) { //迁移覆盖 int dirUnitAmount = myDirTable->dirUnitAmount; for(int i=unitIndex; i<dirUnitAmount-1; i++) { myDirTable->dirs[i] = myDirTable->dirs[i+1]; } myDirTable->dirUnitAmount--; return 0; } //删除目录 rmdir int deleteDir(char dirName[]) { //忽略系统的自动创建的父目录 if(strcmp(dirName, "..") == 0) { printf("can't delete ..\n"); return -1; } //查找文件 int unitIndex = findUnitInTable(currentDirTable, dirName); if(unitIndex == -1) { printf("file not found\n"); return -1; } dirUnit myUnit = currentDirTable->dirs[unitIndex]; //判断类型 if(myUnit.type == 0)//目录 { deleteFileInTable(currentDirTable, unitIndex); }else { printf("not a dir\n"); return -1; } //从目录表中剔除 deleteDirUnit(currentDirTable, unitIndex); return 0; } //删除文件/目录项 int deleteFileInTable(dirTable* myDirTable, int unitIndex) { //查找文件 dirUnit myUnit = myDirTable->dirs[unitIndex]; //判断类型 if(myUnit.type == 0)//目录 { //找到目录位置 int FCBBlock = myUnit.startBlock; dirTable* table = (dirTable*)getBlockAddr(FCBBlock); //递归删除目录下的所有文件 printf("cycle delete dir %s\n", myUnit.fileName); int unitCount = table->dirUnitAmount; for(int i=1; i<unitCount; i++)//忽略“..” { printf("delete %s\n", table->dirs[i].fileName); deleteFileInTable(table, i); } //释放目录表空间 releaseBlock(FCBBlock, 1); }else {//文件 //释放文件内存 int FCBBlock = myUnit.startBlock; releaseFile(FCBBlock); } return 0; } //**********************读写操作 //读文件 read int read(char fileName[], int length) { int unitIndex = findUnitInTable(currentDirTable, fileName); if(unitIndex == -1) { printf("file no found\n"); return -1; } //控制块 int FCBBlock = currentDirTable->dirs[unitIndex].startBlock; FCB* myFCB = (FCB*)getBlockAddr(FCBBlock); doRead(myFCB, length); return 0; } //重新读文件 reread int reread(char fileName[], int length) { int unitIndex = findUnitInTable(currentDirTable, fileName); if(unitIndex == -1) { printf("file no found\n"); return -1; } //控制块 int FCBBlock = currentDirTable->dirs[unitIndex].startBlock; FCB* myFCB = (FCB*)getBlockAddr(FCBBlock); myFCB->readptr = 0; doRead(myFCB, length); return 0; } //执行读操作 int doRead(FCB* myFCB, int length) { //读数据 int dataSize = myFCB->dataSize; char* data = (char*)getBlockAddr(myFCB->blockNum); //在不超出数据长度下,读取指定长度的数据 for(int i=0; i<length && myFCB->readptr < dataSize; i++, myFCB->readptr++) { printf("%c", *(data+myFCB->readptr)); } if(myFCB->readptr == dataSize)//读到文件末尾用#表示 printf("#"); //换行美观 printf("\n"); return 0; } //写文件,从末尾写入 write int write(char fileName[], char content[]) { int unitIndex = findUnitInTable(currentDirTable, fileName); if(unitIndex == -1) { printf("file no found\n"); return -1; } //控制块 int FCBBlock = currentDirTable->dirs[unitIndex].startBlock; FCB* myFCB = (FCB*)getBlockAddr(FCBBlock); doWrite(myFCB, content); return 0; } //重新写覆盖 rewrite int rewrite(char fileName[], char content[]) { int unitIndex = findUnitInTable(currentDirTable, fileName); if(unitIndex == -1) { printf("file no found\n"); return -1; } //控制块 int FCBBlock = currentDirTable->dirs[unitIndex].startBlock; FCB* myFCB = (FCB*)getBlockAddr(FCBBlock); //重设数据块 myFCB->dataSize = 0; myFCB->readptr = 0; doWrite(myFCB, content); return 0; } //执行写操作 int doWrite(FCB* myFCB, char content[]) { int contentLen = strlen(content); int fileSize = myFCB->fileSize * block_szie; char* data = (char*)getBlockAddr(myFCB->blockNum); //在不超出文件的大小的范围内写入 for(int i=0; i<contentLen && myFCB->dataSize<fileSize; i++, myFCB->dataSize++) { *(data+myFCB->dataSize) = content[i]; } if(myFCB->dataSize == fileSize) printf("file is full,can't write in\n"); return 0; } //从目录中查找目录项目 int findUnitInTable(dirTable* myDirTable, char unitName[]) { //获得目录表 int dirUnitAmount = myDirTable->dirUnitAmount; int unitIndex = -1; for(int i=0; i<dirUnitAmount; i++)//查找目录项位置 if(strcmp(unitName, myDirTable->dirs[i].fileName) == 0) unitIndex = i; return unitIndex; }
工程代码链接(含有exe可直接运行): FileSystem
-
c++实现日志系统
2017-01-24 16:27:34软件开发中常常将关键的操作、一般性警告以及严重的错误,通过日志文件的形式输出字符串,本子系统实现bootlog,debuglog,warning,fatallog等输出形式,支持linux、windows两种编译环境,支持多线程。有不到之处... -
C++实现网络文件传输
2012-11-09 21:53:54C++实现多线程网络文件传输、 -
C/C++实现文件加密器
2022-04-05 21:13:23文章目录一、程序逻辑二、代码三、测试结果 一、程序逻辑 二、代码 #include<iostream> #include<... "输入文件路径:"; cin >> fileName; fstream f; f.open(fileName,ios ::in|ios::out|i一、程序逻辑
二、代码
#include<iostream> #include<fstream> #include<string> using namespace std; int main() { string fileName; cout << "输入文件路径:"; cin >> fileName; fstream f; f.open(fileName,ios ::in|ios::out|ios::binary); //以读写二进制打开文件 if (!f.is_open()) { //判断是否打开成功 cout << "打开文件失败"; return -1; } while (f.good()) { //判断当前是否有错误发送,没有则继续 int c = f.get(); //读一个字节,此时文件指针将前进一个 f.seekg(-1,ios::cur); //回退一个字节 f.put(~c); //将读到的字节取反加密,放如原位置 f.seekg(1,ios::cur);//前进一个字节 cout <<"已加密(解密)字节数量:" << f.tellg() << endl;//输出加密信息 } if (f.eof()) { //判断当前是否在文件末尾 cout << "加密(解密)成功!" << endl; } else { cout << "加密(解密)失败!" << endl; } f.close(); }
注意:
- 因为是使用的取反加密,所以加密和解密的程序相同
- 由于是采用的字节加密,所以可以加密任何文件,如exe,视频,音乐等均可以
三、测试结果
原文件:
加密后:
再对该程序运行一次,解密后:
-
c++ 实现虚拟文件系统
2009-01-02 16:31:34用c++来实现一个简单的虚拟文件系统 可以实现 多种基本的文件功能 -
文件系统C++实现
2012-06-15 12:36:13c++实现的文件系统 可以输入指令创建文件删除文件新建文件等 树形结构 采用位示图等 可查看占用磁盘情况 当然这些都是模拟的 当时做的大型实验 带实验报告 -
C++实现的人脸识别系统
2018-10-28 10:27:11这是一个C++语言开发的人脸识别系统,文件包括说明文档,测试数据,源码等实例。 -
c++实现文件实现学生信息管理系统
2018-09-06 21:43:51c++实现文件实现学生信息管理系统 功能如下: 添加学生信息(学生添加完成将直接保存进文件) 成绩信息(c语言,大学英语,高等数学) 个人信息(姓名、性别、学号、年龄) 显示学生信息 查询学生信息 按学号...c++实现文件实现学生信息管理系统
功能如下:
- 添加学生信息(学生添加完成将直接保存进文件)
- 成绩信息(c语言,大学英语,高等数学)
- 个人信息(姓名、性别、学号、年龄)
- 显示学生信息
- 查询学生信息
- 按学号查询
- 按名字查询
- 按学号删除学生信息
- 修改学生信息
- 按学号对学生进行排序
类的设计:
表示成绩的Score类:
class Score{ public: float cLauage;//c语言成绩 float math;//高数成绩 float english;//英语成绩 };
学生类
class Student{ public : char num[10];//学号 int age;//年龄 char name[20];//姓名 char sex[5];//性别 Score sc; };
教师类
class Teacher{ public: Student stu[N]; //N为50 void seek();//查找 void modify();//修改信息 void insert();//插入学生信息 void del();//删除学生 void display();//显示学生信息 void sorts();//按学号排序 void help();//帮助信息 void menu();//菜单 void refresh();//刷新 };
主要功能的实现
插入学生信息
- 主要思想:实例化一个Student对象将输入的学生信息存入该对象,输入完成后将该对象写入文件,代码实现如下:
//插入学生信息 void Teacher::insert(){ int j=n; int m;//要增加的学生人数 cout<<"请输入待增加的学生数:"<<endl; cin>>m; do { Student stu; cout<<"请输入第"<<j-n+1<<"个学生的学号"<<endl;//输入学生信息 cin>>stu.num; cout<<"请输入第"<<j-n+1<<"个学生的姓名"<<endl; cin>>stu.name; cout<<"请输入第"<<j-n+1<<"个学生的年龄"<<endl; cin>>stu.age; cout<<"请输入第"<<j-n+1<<"个学生的性别"<<endl; cin>>stu.sex; cout<<"请输入第"<<j-n+1<<"个学生的C语言成绩"<<endl; cin>>stu.sc.cLauage; cout<<"请输入第"<<j-n+1<<"个学生的高数成绩"<<endl; cin>>stu.sc.math; cout<<"请输入第"<<j-n+1<<"个学生的英语成绩"<<endl; cin>>stu.sc.english; j++; fstream file("student.txt", ios::out | ios::binary | ios::app); file.write((char *)&stu, sizeof(Student));//把该学生对象写入文件 file.close(); }while(j<n+m); n+=m; cout<<"信息增加完毕"<<endl; }
查找学生信息
- 主要思想:将所有学生对象从文件中读取出来,获取该对象的属性值与输入信息做比较,如果相等则找到该学生对象。否则,不存在该学生。代码如下:
- 按学号查找
cout<<"请输入要查询的学生的学号"<<endl; cin>>str; fstream file("student.txt", ios::binary | ios::in);//打开文件 while(!file.eof()) { Student stu; file.read((char *)&stu, sizeof(Student)); if(strcmp(stu.num,str)==0) //判断从文件读出对象的学号信息是否和输入相等 { flag=1; cout<<"学生学号 学生姓名 年龄 性别 C语言成绩 高等数学 大学英语成绩"<<endl; cout<<stu.num<<"\t "<<stu.name<<" \t"<<stu.age<<"\t"<<stu.sex<<"\t"<<stu.sc.cLauage<<" \t"<<stu.sc.math<<"\t\t "<<stu.sc.english<<endl; break; } } if(flag!=1) cout<<"该学号不存在"<<endl; file.close();
- 按姓名查找(只需要获取学生对象的name做比较)
cout<<"请输入要查询的学生的姓名"<<endl; cin>>str; fstream file("student.txt", ios::binary | ios::in); while(!file.eof()) { Student stu; file.read((char *)&stu, sizeof(Student)); if(strcmp(stu.name,str)==0)//判断从文件读出对象的姓名信息是否和输入相等 { flag=1; cout<<"学生学号 学生姓名 年龄 性别 C语言成绩 高等数学 大学英语成绩"<<endl; cout<<stu.num<<"\t "<<stu.name<<" \t"<<stu.age<<"\t"<<stu.sex<<"\t"<<stu.sc.cLauage<<" \t"<<stu.sc.math<<"\t\t "<<stu.sc.english<<endl; break; } } if(flag!=1) cout<<"该学生不存在"<<endl; file.close();
显示学生信息
- 主要思想:将学生信息从文件读出来进行显示。代码如下:
void Teacher::display(){ int flag; int t=0; fstream file("student.txt", ios::binary | ios::in); cout<<"学生学号 学生姓名 年龄 性别 C语言成绩 高等数学 大学英语成绩"<<endl; while(!file.eof()) { Student stu; file.read((char *)&stu, sizeof(Student));//从文件读出所有学生信息 flag=1; cout<<stu.num<<"\t "<<stu.name<<" \t"<<stu.age<<"\t"<<stu.sex<<"\t"<<stu.sc.cLauage<<" \t"<<stu.sc.math<<"\t\t "<<stu.sc.english<<endl; } if(flag!=1) cout<<"无该学生"<<endl; file.close(); }
修改学生信息
- 主要思想:将需要修改的学生按学号从文件中取出,为该对象设置新的值,最终在写入文件。代码如下:
void Teacher::modify(){ int item,age,score;//选择修改项,修改年龄 Student stu; int flag; char str[20];//暂时存修改内容 cout<<"请输入要查询的学生的学号"<<endl; cin>>str; fstream file("student.txt", ios::binary | ios::in);//打开文件存取学生对象的文件 while(!file.eof()) { file.read((char *)&stu, sizeof(Student));//读取文件 if(strcmp(stu.num,str)==0)//如果存在学生信息输出 { flag=1; cout<<"学生学号 学生姓名 年龄 性别 C语言成绩 高等数学 大学英语成绩"<<endl; cout<<stu.num<<"\t "<<stu.name<<" \t"<<stu.age<<"\t"<<stu.sex<<"\t"<<stu.sc.cLauage<<" \t"<<stu.sc.math<<"\t\t "<<stu.sc.english<<endl; break; } } if(flag!=1)//如果不存在则提示无该学生 cout<<"该学生不存在"<<endl; file.close(); printf("------------------\n"); printf("1.修改姓名\n"); printf("2.修改年龄\n"); printf("3.修改性别\n"); printf("4.修改C语言成绩\n"); printf("5.修改高等数学成绩\n"); printf("6.修改大学英语成绩\n"); printf("7.退出本菜单\n"); printf("------------------\n"); while(1) { printf("请选择子菜单编号:"); scanf("%d",&item); switch(item) { case 1: printf("请输入新的姓名:\n"); cin>>str; strcpy(stu.name,str); break;//为学生姓名赋新值 case 2: printf("请输入新的年龄:\n"); cin>>age; stu.age=age;break;//为学生年龄赋新值 case 3: printf("请输入新的性别:\n"); cin>>str; strcpy(stu.sex,str); break;//为学生性别赋新值 case 4: printf("请输入新的C语言成绩:\n"); cin>>score; stu.sc.cLauage=score; break;//为学生成绩复新制 case 5: printf("请输入新的数学成绩:\n"); cin>>score; stu.sc.math=score; break; case 6: printf("请输入新的英语成绩:\n"); cin>>score; stu.sc.english=score; break; case 7:{ fstream file("student.txt", ios::out | ios::binary | ios::app); cout<<"修改成功"<<endl; file.write((char *)&stu, sizeof(Student));//把新的学生信息写入文件 file.close(); return; } default:printf("请在1-7之间选择\n"); } } }
删除学生信息
- 主要思想: 将所有学生对象从文件从读出,把读出的不包括需要删除学生的对象存入vector容器,最终将遍历该vector容器,将所有对象存入文件。代码如下:
void Teacher::del(){ vector<Student> va; Student stu;//将读出的学生信息存入该对象 int flag; char str[20]; cout<<"请输入要删除的学生的学号"<<endl; cin>>str; fstream file("student.txt", ios::binary | ios::in);//打开文件存取学生对象的文件 while(!file.eof()) { file.read((char *)&stu, sizeof(Student));//读取文件 if(strcmp(stu.num,str)==0)//如果存在学生信息输出 { flag=1; continue; } va.push_back(stu);//将非删除的学生存入容器 } fstream file1("student.txt", ios::out | ios::trunc); for (int i=0;i<va.size();i++) { file1.write((char *)&va[i], sizeof(Student));//将容器中的学生对象写入文件 } cout<<"删除成功"<<endl; file.close();//关闭文件 file1.close(); }
排序功能
- 主要思想:将所有的对象信息从文件中读出存入vector容器,使用sort()方法结合自定义排序实现学生按学号排序,最终将排序号的遍历写入文件。代码如下:
static bool myCompare(const Student& a1,const Student& a2)//自定义排序 { return strcmp(a1.num,a2.num)<=0;//按学号从小到大排序 } void Teacher::sorts(){ vector<Student> va; Student stu; fstream file("student.txt", ios::binary | ios::in);//打开文件存取学生对象的文件 while(!file.eof()) { file.read((char *)&stu, sizeof(Student));//读取文件 va.push_back(stu);//将学生对象存入容器 } va.pop_back(); sort(va.begin(),va.end(),myCompare);//使用sort进行排序 fstream file1("student.txt", ios::out | ios::trunc); for (int i=0;i<va.size();i++) { file1.write((char *)&va[i], sizeof(Student));//将排序好的写入文件 } file.close();//关闭文件 file1.close(); }
刷新功能
- 主要思想:对学生信息进行排序并输出
//刷新 void Teacher::refresh(){ Teacher t; t.sorts(); t.display(); }
遇到的问题:在从文件读出信息时使用的eof()方法判断是否读到末尾时当读到最后一个字符时,程序会多读一次(编译器会让指针停留在最后一个字符那里,然后重复读取一次,使用while(file.peek() != EOF)就可以解决。
运行截图
添加(在之前的测试中存入了一些数据)
查询
删除
刷新
修改
- 添加学生信息(学生添加完成将直接保存进文件)
-
基于c++的文件管理系统
2011-01-17 12:37:59文件管理系统作为一个统一的信息管理... 实现文件从名字空间到外存地址空间的映射,即实现文件的按名存取。有效实现对文件的各种控制操作(如建立、撤销、打开、关闭文件等)和存取操作(如读、写、修改、复制、转储等)。 -
C++设计实现日志系统
2019-11-16 20:32:18日志系统几乎是每一个实际的软件项目从开发、测试到交付,再到后期的维护...本文Jungle将用C++设计实现一个日志系统。 1.为什么需要日志 为什么需要日志?其实在引言中已经提到了,实际的软件项目的几乎每个过... -
C++实现的模拟文件系统
2010-09-01 11:04:02操作系统课程设计 C++实现 具有4个基本功能 1.建立文件 2.删除文件 3.读文件 4.写文件 -
C++模拟实现的一个VFS(虚拟文件系统)
2011-01-09 21:20:04自己在操作系统课程设计时做的模拟实现VFS系统,供大家参考。(里面有报告和源代码,标准C++代码可以在Linux通过g++编译) 摘要:本文利用虚拟文件系统(VFS)思想,建立一个...并基于此接口实现了一个简单的文件系统。 -
用户权限管理模块(C++实现)
2018-05-25 21:34:361.使用C++实现的权限管理模块 2.单例模式实现,方便集成 3.实现了root和普通用户区别,添加新用户,修改密码 4.用户名密码以加密文档形式存在本地文件 -
C++实现通讯录管理系统
2021-10-19 17:25:48目录前言结构体联系人结构体...完成通讯录管理系统所需知识体系 1.结构体 2.指针 3.函数的封装 4.指针与函数的结合使用 5.指针与结构体的结合使用 结构体 联系人结构体 struct person { string name;//姓名 strin -
多文件系统 C++实现
2009-01-01 12:11:01多文件系统 C++实现 多文件系统 C++实现 多文件系统 C++实现 多文件系统 C++实现 -
C++ 实现FTP上传文件
2020-07-24 16:57:29上传过程中注意处理编码问题: 在Windows系统默认编码格式为GB2312,而在Linux下默认的编码格式为UTF8,当文件在不同操作系统之间传输时,为了避免中文乱码,需要对文件编码格式进行转换。从Windows传到Linux时需要... -
c++实现文件目录查找
2019-08-19 16:27:09c++文件查找需要调用库:io.h,以及库中的两个函数:_findfist和_findnext 文件结构体: struct _finddata_t { unsigned attrib; time_t time_create; time_t time_access; time_t time_write; ... -
C++文件传输系统的实现
2011-03-08 16:56:06编程语言是C++,编译环境是Visual C++ 6.0,实现的是文件在客户和服务器端的传输,编译通过可运行 -
C++语言实现一个类UNIX文件系统
2010-04-24 14:44:00C++语言实现一个类UNIX文件系统,实现文件的创建、打开、读写、删除、及目录的创建、查看、删除等操作。 -
基于C++的文件管理系统
2019-07-24 22:35:58模拟实现linux文件系统。inode、superBlock…… The simulation of the ...通过C++调用linux系统函数,一块硬盘(创建的一个文件,本程序中是DISK)上实现一个简单的linux文件系统。 点击此处下载文档和源码... -
C++实现登录注册(文件储存和读取)
2021-01-19 23:24:51C++实现登录注册,并将数据保存到文件(txt文档中) 实现要求: 1.如果不存在初始用户数据文件则创建用户数据文件 2.实现完整的注册登录 3.实现用户数据的自动保存和读取 4.密码输入提供直接显示和隐式显示 1.运行...