其实,刚拿到这个题目时,我真的没有思路,随后我就对着老师的课设指导书进行研究,对二级文件系统的演示这个课题的每个要求进行分析,总算是有了思路。下面给出我的分析。
文件系统演示
一、课程设计目的
使学生熟悉文件管理系统的设计方法;加深对所学各种文件操作的了解及其操作方法的特点。
//既然是基于控制台的,我们可以更改颜色玩玩
二、课程设计内容
设计一个简单的多用户文件系统。即 //和后面一样,用结构体数组实现
①在系统中用一个文件来模拟一个磁盘; //switch语句或者if-else语句实现,既然这里说到了 用一个文件去模拟一个磁盘,换句话说,在你的课设里,必须要有磁盘空间分配的思路在里面,不然就不是模拟磁盘了。
②此系统至少有:Create、delete、open、close、read、write等和部分文件属性的功能。
③实现这个文件系统。 //文件系统要实现
④能实际演示这个文件系统。//cmd演示即可
基本上是进入一个界面(此界面就是该文件系统的界面)后,可以实现设计的操作要求。
三、课程设计指导
1)设计一个10个用户的文件系统,每次用户可保存10个文件,一次运行用户可以打开5个文件。 //三个数组的大小分别为 10、10、5
//一次运行用户最多可以打开5个文件如何实现? 在用户文件里面加变量判断,用户每打开一个就+1,
//每次用户最多可保存10个文件如何实现? 很明显,同时保存我们是无法做到的,无论是谁,都无法做到,也就是说还是一个个保存的,那么同样可以设置变量判断。如果保存的较多,那么只好请用户单独关闭某些指定的文件。
2)程序采用二级文件目录(即设置主目录MFD)和用户文件目录(UFD)。另外,为打开文件设置了运行文件目录(AFD)。 //存放各个用户目录的文件夹、用户目录
//是说运行的所有文件用一个目录层次表示吗
3)为了便于实现,对文件的读写作了简化,在执行读写命令时,只需改读写指针,并不进行实际的读写操作。 //整型的变量判断是否读写完成了 下面的pointer
4)因系统小,文件目录的检索使用了简单的线性搜索。 //链表的顺序查找
5)文件保护简单使用了三位保护码:允许读写执行、对应位为 1,对应位为0,则表示不允许读写、执行。 //标记变量即可实现
6)程序中使用的主要设计结构如下:主文件目录和用户文件目录(MFD、UFD),打开文件目录(AFD)即运行文件目录,如图5.1所示。//主要的结构体设计
还有MFD、UFD、AFD最好全部存到文件里面去,不然每次都要输入,十分麻烦,而且不能通过看文件 查看到自己的实验现象,着实不便。
参考的数据结构设计如下
struct TYPE_UFD //用户文件目录
{
string File_Name; //文件名
bool Read; //读保护码,true为可读
bool Write; //写保护码,true为可写
bool Execute; //执行保护码,true为可执行
int Length_File; //文件长度
}; //用户文件目录和用户打开的文件目录是不是都各有自己的属性
struct TYPE_MFD //主文件目录
{
string User_Name; //用户名
TYPE_UFD *Pointer; //用户文件目录指针
};
//很明显,第三个结构体没有指针域,但我们是需要指针域的,还有下面红色部分可以合在一个整型变量里面的
struct TYPE_AFD //打开文件目录
{
int File_ID; //打开的文件号
boolRead;//读保护码,true为可读
boolWrite;//写保护码,true为可写
boolExecute;//执行保护码,true为可执行
int Pointer; //读写指针
};
7)文件系统结构如图5.2所示
//很明显,这里要用到的数据结构是 链表
8)文件系统算法的流程图如图5.3所示。
图5.3文件系统算法的流程图
//这里告诉了你 main函数的主要调用的函数顺序
9)注意对于物理块的访问(包括访问指针,空闲位)需要经过输入输出,相当于通过定位对文件进行读写。打开文件目录(AFD)是在内存中,由打开文件时创建。
好了,分析完了,就要开始编写代码了,下面附上我小小的代码,还有很多需要修改的地方,做的不好的地方,大神就请原谅,也希望多多指点我。
先附上效果图:
头文件部分:
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef struct UFD
{
string File_name; //文件名
int Start; //文件在磁盘存储空间的起始地址
int Protect; //文件的属性
int File_length; //文件的长度
int Max_File_length; //文件的最大长度
struct UFD *next;
}UFD,*UFD_ptr;
typedef struct MFD
{
string User_name;
string User_passwd;
UFD *Ufd_next;
int End;
struct MFD *next;
}MFD,*MFD_ptr;
typedef struct AFD
{
string File_name;
int File_length;
int Start;
int Protect;
int Pointer; //根据这个指针的值去完成用户的要求 读写指针
int Max_File_length;
struct AFD *next;
}AFD,*AFD_ptr;
源文件部分:
#include"os_fss.h"
#define MaxDisk 512*1024 //一个扇区512字节,假设有1024个扇区,模拟磁盘的大小
int Max_User=10;
int Max_Open=5;
int Max_End=0;
UFD_ptr pufd=NULL;
MFD_ptr pmfd=NULL;
AFD_ptr pafd=NULL;
char User_name[30]; //存放当前用户的用户名
char flag='n';
char Disk_Size[MaxDisk]; //最后在打印输出的时候,用RWX表示即可
typedef struct Disk_Table
{
int Max_length; //最大长度
int Start; //开始位置
}Disk_Node;
Disk_Node Disk_Head;
void Init_Disk()
{
Disk_Head.Max_length=MaxDisk;
Disk_Head.Start=0;
}
bool Init_MFD()
{
pmfd=(MFD *)new MFD; //带头节点的单向链表
MFD *p=pmfd;
ifstream ifs("MFD.txt"); //文件的输入流对象
if(!ifs)
{
cerr<<"错误:无法打开文件"<next=NULL;
p->Ufd_next=NULL;
return false;
}
while(!ifs.eof())
{
p->next=(MFD *)new MFD;
ifs>>p->next->User_name>>p->next->User_passwd>>p->next->End;
if(p->next->End>Max_End)
Max_End=p->next->End;
p=p->next;
p->Ufd_next=NULL;
p->next=NULL;
}
ifs.close();
return true;
}
void Print_UFD()
{
UFD *p=pufd->next;
if(!p)
{
cout<<"抱歉,该用户没有创建任何文件,请先创建!!!"<File_name<<"\t\t"<Max_File_length;
if(p->Protect==0)
cout<<"\t\t"<<"---";
else if(p->Protect==1)
cout<<"\t\t"<<"r-x";
else if(p->Protect==2)
cout<<"\t\t"<<"rwx";
cout<<"\t\t"<Start;
cout<<"\t\t"<File_length<next;
}
}
bool Init_UFD(char *name)
{
ifstream ifs(name);
pufd=(UFD *)new UFD;
UFD *p=pufd;
char temp[MaxDisk];
bool Index=false;
if(!ifs)
{
cerr<<"错误:无法打开文件"<next=NULL;
return false;
}
while(!ifs.eof())
{
memset(temp,'\0',sizeof(temp));
p->next=(UFD *)new UFD;
if(!Index)
{
pmfd->Ufd_next=p->next;
Index=true;
}
ifs>>p->next->File_name>>p->next->Max_File_length>>p->next->Protect>>p->next->Start>>p->next->File_length;
ifs>>temp;
if(temp[0]=='#')
temp[0]='\0';
for(int i=p->next->Start,j=1;j<=p->next->Max_File_length-1;i++,j++)
{
Disk_Size[i]=temp[j-1];
if(!Disk_Size[i])
break;
}
Disk_Head.Max_length-=p->next->Max_File_length;
// Disk_Head.Start+=p->next->Max_File_length;
p=p->next;
p->next=NULL;
}
ifs.close();
return true;
}
void Rename_File()
{
string File_name;
UFD *temp=pufd;
char Index;
SD:
cout<<"请输入文件的名字:"<>File_name;
while(temp)
{
if(temp->File_name==File_name)
{
cout<<"请输入新的文件名:"<>File_name;
temp->File_name=File_name;
break;
}
temp=temp->next;
}
if(!temp)
{
cout<<"抱歉,输入的文件不存在,无法完成重命名文件操作,是否继续操作?"<>Index;
if(Index=='y')
goto SD;
else
return ;
}
else
cout<<"修改成功!!!"<>User_name;
INIT:
cout<<"请输入密码:";
cin>>User_passwd;
MFD *p=pmfd->next;
char temp[30];
memset(temp,'\0',sizeof(temp));
strcpy(temp,User_name);
Count++;
while(p)
{
if(User_name==p->User_name)
{
if(User_passwd==p->User_passwd)
cout<<"登入成功."<next;
}
cout<<"用户名不存在,请重新输入!!!"<next=NULL;
}
bool Create_MFD()//创建文件命令
{
string User_name;
char User_passwd[30];
MFD *p = pmfd;
cout<<"请输入要创建的用户名: ";
cin>>User_name;
cout<<"请输入"<User_name)
{
cout<<"此用户名已存在!!!"<next)
break;
p= p->next;
}
p->next = (MFD *)new MFD; //尾插法
p=p->next;
p->User_name=User_name;
p->User_passwd=User_passwd;
p->End=0;
p->next = NULL;
p->Ufd_next = NULL;
Max_User--;
return true;
} //应该是 不同的用户下的UFD文件名是不一样的啊,怎么出问题了
bool Create_UFD()//创建文件命令
{
string File_name;
UFD *p = pufd;
unsigned int Protect;
int Max_File_length;
// AFD *pa = pafd;
cout<<"请输入要创建的文件名: ";
cin>>File_name;
cout<<"请输入要创建的文件保护类型:";
cin>>Protect;
cout<<"请输入文件的最大容量:"<>Max_File_length;
while(p)
{
if(File_name==p->File_name)
{
cout<<"此文件名已存在!!!"<next)
break;
p= p->next;
}
p->next = (UFD *)new UFD; //尾插法
p=p->next;
p->File_name=File_name;
p->Max_File_length=Max_File_length;
p->Start=Disk_Head.Start;
p->Protect = Protect;
// p->Time_info= //暂定
p->File_length = 0; //刚创建文件时,文件是空的
Disk_Head.Start+=Max_File_length;
p->next = NULL; //我觉得这部分代码有问题;用户创建了一个文件并不代表该文件就被打开了
return true;
}
bool Delete_UFD() //关于主目录的用户文件夹的文件删除-->先这样写,好吧 //如果文件已经打开了,是不能删除的
{
string File_name;
cout<<"请输入要删除的文件名:";
cin>>File_name;
UFD *p=pufd,*temp;
AFD *pa=pafd;
while(pa->next)
{
if(File_name==pa->next->File_name)
{
cout<<"抱歉,该文件已被打开,请先关闭,再进行删除操作!!!"<next)
{
if(File_name==p->next->File_name)
{
temp=p->next;
p->next=p->next->next; //如果说要回收模拟的磁盘空间的话,应该是回收最大长度
// Disk_Head.Max_length+=temp->Max_File_length; //链表中删除了,其他的文件内容的起始位置不变即可,又没事,还是照样可以访问数据的嘛
delete temp;
cout<<"文件删除成功!!!"<next;
}
cout<<"抱歉,要删除的文件不存在!!!"<>File_name;
UFD *p=pufd->next;
AFD *pa=pafd->next;
while(pa)
{
if(File_name==pa->File_name)
{
cout<<"文件"<next)
break;
pa=pa->next;
}
if(!pa) //如果找不到,或者打开的文件目录链表为空表
pa=pafd;
while(p)
{
if(File_name==p->File_name)
{
if(!Max_Open)
{
cout<<"抱歉,最多只能打开5个文件,请先关闭其他打开的文件再操作!!!"<Protect==0)
{
cout<<"抱歉,此文件不可执行任何操作!!!"<:";
cin>>Protect;
pa->next=(AFD *)new AFD;
pa=pa->next;
pa->File_name=p->File_name;
pa->Start=p->Start;
pa->File_length=p->File_length;
pa->Max_File_length=p->Max_File_length;
pa->Protect=Protect;
if(Protect==1)
pa->Pointer=0; //Poniter取0表示此时用户无法写数据(没有空间的含义)
else
pa->Pointer=p->File_length;
pa->next=NULL;
Max_Open--;
cout<<"文件"<next;
}
cout<<"抱歉,要打开的文件不存在!!!"<next;
cout<<"请输入要关闭的文件名:";
cin>>file_name;
AFD *p=pafd,*temp;
while(p&&p->next)
{
if(file_name==p->next->File_name)
{
temp=p->next;
p->next=p->next->next;
if(temp->Protect==2) //可写的文件才有权把新写入的数据也保存起来嘛
{
while(pu)
{
if(temp->File_name==pu->File_name)
{
pu->File_length=temp->Pointer;
break;
}
pu=pu->next;
}
}
delete temp;
cout<<"文件"<next;
}
cout<<"抱歉,要关闭的文件没有被打开!!!"<next;
cout<<"请输入要读的文件名:";
cin>>File_name;
cout<<"请输入要读取的长度:"; //读取的话,实际中文件的长度并不会改变
cin>>length; //即读取的长度并不能保存回去,为了方便(如果用户是读数据的话,pointer始终不变)
while(p)
{
if(File_name==p->File_name)
{
for(int i=p->Start,j=1;j<=length;i++,j++)
cout<next;
}
cout<<"读取失败,文件没有打开过!!!"<next;
char temp[MaxDisk]={'\0'};
cout<<"请输入要写的文件名:";
cin>>File_name;
while(p)
{
if(File_name==p->File_name)
{
if(p->Protect!=2)
{
cout<<"文件"<>length;
if(p->Pointer+length<=p->Max_File_length)
{
cout<<"请写入指定长度的内容:<以回车作为结束符>"<Start+p->File_length,j=1;j<=strlen(temp);i++,j++)
Disk_Size[i]=temp[j-1];
p->Pointer += length;
cout<<"文件"<next;
}
cout<<"写入失败,文件没有打开过!!!"<next;
delete pm;
pm=pmfd;
}
AFD *pa=pafd;
while(pa)
{
pafd=pafd->next;
delete pa;
pa=pafd;
}
UFD *pu=pufd;
while(pu)
{
pufd=pufd->next;
delete pu;
pu=pufd;
}
}
void Save_MFD()
{
ofstream ofs; //文件的输出流对象
ofs.open("MFD.txt");
if(!ofs.is_open())
{
cout<<"The MFD can't open!!!"<next;
while(p)
{
if(p->User_name==User_name)
p->End=Disk_Head.Start;
ofs<User_name<<" "<User_passwd<<" "<End;
if(p->next)
ofs<<"\n";
p=p->next;
}
ofs.close();
}
void Save_UFD(char *name)
{
ofstream ofs; //文件的输出流对象
char temp[MaxDisk]={'\0'};
ofs.open(name);
if(!ofs.is_open())
{
cout<<"The "<next;
while(p)
{
memset(temp,'\0',sizeof(temp));
for(int i=p->Start,j=1;j<=p->Max_File_length;i++,j++)
{
if(Disk_Size[i])
temp[j-1]=Disk_Size[i];
else
break;
}
if(!temp[0]) //如果文件没有数据的话,就用空格表示此文件没有任何内容
temp[0]='#';
ofs<File_name<<" "<Max_File_length<<" "<Protect<<" "<Start<<" "<File_length<<" "<next)
ofs<<"\n";
p=p->next;
}
ofs.close();
}
void Quit_System()
{
AFD *pa=pafd->next;
UFD *pu=pufd->next;
while(pa)
{
if(pa->Protect==2) //2表示可写 //1表示只读 //0表示不可操作
{
while(pu)
{
if(pa->File_name==pu->File_name)
{
pu->File_length=pa->Pointer;
break;
}
pu=pu->next;
}
}
pa=pa->next;
}
char temp[30];
strcpy(temp,User_name);
strcat(temp,".txt");
Save_MFD();
Save_UFD(temp);
Print_UFD();
Destroy_Space();
}
void Print_Help()
{
system("color 0b");
cout<<"************************二级文件系统演示*************************"<!!!"<>flag;
cout<<"请输入欲创建的用户文件夹的个数(1-10):"<>num;
if(flag=='y')
{
while(num--)
{
Create_MFD();
if(!Max_User)
{
cout<<"本系统,最多支持10个用户,创建多余用户失败,请删除其他用户,再做尝试!!!"<!!!"<>flag;
if(flag=='y')
goto Start;
}
}
return ;
}
void File_System()
{
while(1)
{
string Command;
cout<<"请输入命令:";
cin>>Command;
if(Command=="create")
Create_UFD();
else if(Command=="delete")
Delete_UFD();
else if(Command=="open")
Open();
else if(Command=="close")
Close();
else if(Command=="read")
Read_File();
else if(Command=="write")
Write_File();
else if(Command=="quit")
{
Quit_System();
break;
}
else if(Command=="ls")
Print_UFD();
else if(Command=="cls")
system("cls");
else if(Command=="login")
{
if(!User_Check())
break;
Init_AFD();
}
else if(Command=="rename")
Rename_File();
else if(Command=="logout")
{
cout<<"用户登出成功!!!"<