浙江工业大学计算机学院
实 验 报 告
实验名称 操作系统课程设计
姓 名
学 号
班 级
教 师
日 期 2019.1.21
一、实验目的
模拟文件系统的实现的基本功能,了解文件系统的基本结构和文件系统的管理方法看加深了解文件系统的内部功能的实现。通过高级语言编写和实现一个简单的文件系统,模拟文件管理的工作过程,从而对各种文件操作系统命令的实质内容和执行过程有比较深入的了解。
二、实验内容和要求
开发工具:word,vc,win32api
设计和实现一个模拟文件系统,要求包括目录、普通文件和文件的存储。必须有自定义的数据结构,不能直接调用windows 的API函数,即不能只实现一个壳。
文件系统的目录结构采用类似Linux的树状结构。
要求模拟的操作包括:
1.目录的添加、删除、重命名;
2.目录的显示(列表)
3.文件的添加、删除、重命名
4.文件和目录的拷贝
5.文件的读写操作
6.用户进入时显示可用命令列表;用户输入help时显示所有命令的帮助文档; 输入某个命令+?时显示该条命令的使用说明。
7.用户输入exit时退出该系统。
实验实现基于windows平台,开发语言必须选用C/C++,不能选用JAVA。
三、概要设计
在我们的文件管理系统中,主要存在两类用户(管理员和普通用户)对文件进行管理。这两类用户共用一个目录,主要区别在于管理文件权限的不同。主要的数据结构包括数据块(disk)文件类(File)和目录类(Directory),如下图所示。
数据块块地址块占用情况块内容 | 文件类文件名文件属性文件大小文件读写属性文件的共享文件是否打开文件与数据块对应 | 目录类目录名文件大小目录读写属性文件夹共享文件数目上一级目录指针 |
---|---|---|
文件名 | ||
文件属性 | ||
文件大小 | ||
文件读写属性 | ||
文件的共享 | ||
文件是否打开 | ||
文件与数据块对应 |
图3.1 系统主要的数据结构
- 数据块(disk)用于存放数据的结构,数据包括文件的内容和目录的内容。在本系统中,考虑到实用性和方便性,数据块由数组实现。
struct diskblock
{
bool occupy=0; //是否被占用
char block[blockSize]; //块的内容
};
struct disk
{
int freeblock = blockNum;
diskblock Disk[blockNum];
}; - 文件类(File),用于存放文件的数据结构。文件与数据块和目录的连接有指针实现。
class File
{
public:
char FileName[20];//文件名
char FileType[4]; //文件属性
int FileLength; //文件的大小
bool readOnly; //只读
bool shared; //文件的共享
bool isOpen; //文件是否打开
private:
int* Index; //文件与数据块的对应
}
3.目录类(Directory)主要是连接文件,由于此操作系统使用了树的结构,所以目录结构中相应加入了用于树结构的father等记录链接情况。
class Directory
{
public:
char dirName[20];//目录名
int dirLength; //文件的大小
bool readOnly; //只读
bool shared; //文件夹的共享
int subDirMaxNum = INITNUM;
int fileMaxNum = INITNUM;
int filenum;
int subdirnum;
private:
Directory* fatherDir;
Directory** subDir;
File** filelist;
}
关键函数说明:
初始化函数
void initializeSystem();
对目录进行操作
Directory* getfatherDir();
Directory* getSubDir(const char*nanme);
File* getFile(const char* name);
int mkDir(const char* dirname);
int delDir(const char* dir);
对文件的基本操作
int createFile(const char* dirname);
int delFile(const char* file);
void reName(const char* name);
char* readFile()const;
void writeFile( const char* buffer);
File* copyFile()const;
总体的流程图如下:
四、详细设计
4.1顶层模块划分
图4.1 顶层模块划分
4.2用户登录模块
图4.2 用户登录流程图
4.3用户创建文件模块
图4.3 用户创建文件流程图
4.4用户删除文件模块
图4.4用户删除文件流程图
4.5用户读取文件模块
图4.5 用户读取文件流程图
4.6用户写入文件模块
图4.6用户写入文件流程图
4.7用户复制文件模块
图4.7 用户复制文件流程图
五、代码
File.h
#pragma once
#include<string>
#include<iostream>
#define blockNum 10000
#define blockSize 255
struct diskblock
{
bool occupy=0; //是否被占用
char block[blockSize];//块的内容
};
struct disk
{
int freeblock = blockNum;
diskblock Disk[blockNum];
};
extern disk d;
class File
{
public:
char FileName[20];//文件名
char FileType[4];//文件属性
int FileLength; //文件的大小
bool readOnly; //只读
bool shared; //文件的共享
bool isOpen; //文件是否打开
bool isExe;//是否可执行
bool isNetwork;//是否可传输
private:
int* Index;//*文件与数据块的对应
int user;//用户所有者
public:
File();
File(const char* filename);
int getFilelength()const;//获取保存文件的大小
void reName(const char* name);//重命名
char* readFile()const;//读文件
void writeFile( const char* buffer);//写文件
File* copyFile()const;//复制文件
~File();
};
int* memory_allocate(int n);//为文件分配内存
void memory_back(int *Index,int n);//回收文件占用内存
Directory.h
#pragma once
#include"File.h"
#include<vector>
#include<string>
#define INITNUM 20
class Directory
{
public :
public:
char dirName[20];//目录名
int dirLength; //文件的大小
bool readOnly; //只读
bool shared; //文件夹的共享
bool isExe;//是否可执行
bool isNetwork;//是否可传输
int subDirMaxNum = INITNUM;//初始最多的子目录数
int fileMaxNum = INITNUM;//初始最多文件数
int filenum;//现在的文件数
int subdirnum;//现在的子目录数
private:
Directory* fatherDir;//父目录
Directory** subDir;//子目录
File** filelist;//文件
int user;//用户所有者
public:
Directory();
Directory(const char* dirname,Directory* father );
int getDirlength()const;//获取文件的大小
void reName(const char* name);//文件夹重命名
Directory* copyDirectory( Directory* father)const;//复制当前目录
int insertFile(File* f);//将一个文件复制到当前目录下
int insertDirectory(Directory* dir);//将一个目录复制到当前目录下
void printDir();//显示这个目录的信息
Directory* getfatherDir();//获取父目录节点
Directory* getSubDir(const char*nanme);//获得子目录
File* getFile(const char* name);//获得文件
int mkDir(const char* dirname);//新建一个目录
int createFile(const char* dirname);//新建一个文件
int delFile(const char* file);//删除文件
int delDir(const char* dir);//删除子目录
private:
void pdelFile(File* f); //内部调用的删除文件函数
void pdelDir(Directory* dir );//内部调用的删除目录函数
~Directory();
};
using namespace std;
Directory* getDirectory(vector<string> path, Directory* dir);//依据路径获取目录
File* getFile(vector<string>path, Directory* dir);//依据路径获取文件
File.cpp
#include "pch.h"
#include "File.h"
#pragma warning(disable:4996)
using namespace std;
disk d = disk();
File::File()
{
}
File::File(const char* filename)
{
strcpy(this->FileName, filename);
this->readOnly = false;
this->shared = false;
int len = strlen(filename);
strncpy(this->FileType, filename + len - 3, 3);//获取文件类别
this->FileLength = 0;
}
int File::getFilelength()const
{
return this->FileLength;
}
void File::reName(const char* name)
{
strcpy(this->FileName, name);
int len = strlen(name);
strncpy(this->FileType, name + len - 3, 3);
}
char* File::readFile()const //读文件
{
if (Index == NULL)//如果文件为空
return NULL;
/*计算文件大小*/
int n = this->FileLength / blockSize + 1;
/*分配空间*/
char * content = new char[n*blockSize];
int i;
/*获取文件内容*/
for (i = 0; i < n; ++i)
strncpy(content + i * blockSize, d.Disk[Index[i]].block, blockSize);
return content;
}
void File::writeFile(const char* buffer)
{
if (buffer == NULL)
return;
int len = strlen(buffer);//计算缓冲大小
this->FileLength = len;
int n = len / blockSize + 1;
Index = memory_allocate(n);//获得分配到的内存空间地址
if (NULL == Index)//没有分配成功
{
cout << "内存空间不够" << endl;
return;
}
for (int i = 0; i < n; ++i)
{
strncpy(d.Disk[Index[i]].block, buffer + i * blockSize, blockSize);//将文件内容复制过去
}
return;
}
File* File::copyFile()const
{
File* f = new File(this->FileName);//复制文件
f->FileLength = this->FileLength;
f->writeFile(this->readFile());//复制文件内容
return f;
}
int* memory_allocate(int n)
{
if (d.freeblock < n)//内存空间是否充足
return NULL;
int* index = new int[2 * n];//提供足够的缓冲
int i, count = 0;
for (i = 0; i < blockNum; ++i)
{
if (count == n)
{
break;
}
if (d.Disk[i].occupy == 0)
{
index[count++] = i;
d.Disk[i].occupy = 1;
}
}
d.freeblock -= count;//修改内存信息
return index;
}
void memory_back(int *Index,int n)
{
for (int i = 0; i < n; ++i)
{
d.Disk[Index[i]].occupy = 0;
memset(d.Disk[Index[i]].block, sizeof(char)*blockSize, 0);//清空内容
}
d.freeblock += n;
}
File::~File()
{
if (this->FileLength > 0)
{
int n = this->FileLength / blockSize + 1;
memory_back(Index, n);
}
delete Index;
}
Directory.cpp
#include "pch.h"
#include "Directory.h"
#include <cstdio>
#pragma warning(disable:4996)
Directory::Directory()
{
}
Directory::~Directory()
{
this->pdelDir(this);
}
Directory::Directory(const char* dirname, Directory * father)//初始化
{
strcpy(this->dirName, dirname);
this->fatherDir = father;
subDir = new Directory*[subDirMaxNum];
filelist = new File*[fileMaxNum];
this->dirLength = 0;
}
int Directory::getDirlength()const //获得目录的大小
{
return dirLength;
}
void Directory::reName(const char* name)//重命名
{
strcpy(this->dirName, name);
}
Directory* Directory::copyDirectory( Directory* father)const//复制目录
{
Directory* dst = new Directory(this->dirName, father);
dst->readOnly = this->readOnly;
dst->shared = this->shared;
dst->subDirMaxNum = this->subDirMaxNum;
dst->fileMaxNum = this->fileMaxNum;
dst->filenum = this->filenum;
dst->subdirnum = this->subdirnum;
dst->filelist = new File*[fileMaxNum];
dst->subDir = new Directory*[subDirMaxNum];
//文件拷贝
int i;
for (i = 0; i < this->filenum; ++i)
{
dst->filelist[i] = this->filelist[i]->copyFile();
}
//目录拷贝
for(i = 0;i<this->subdirnum;++i)
{
dst->subDir[i] = this->subDir[i]->copyDirectory(subDir[i]);
}
return dst;
}
int Directory::insertFile(File* f) //挂在文件
{
if (filenum + 1 == fileMaxNum) //扩容
{
fileMaxNum *= 2;
File** temp = new File*[fileMaxNum];
for (int i = 0; i < fileMaxNum; ++i)
temp[i] = filelist[i];
delete filelist;
filelist = temp;
}
File* f2 = this->getFile(f->FileName);
if (f2 != NULL)
return -1;//文件已存在
filelist[filenum++] = f;
return 0;
}
int Directory::insertDirectory(Directory* dir) //挂载目录
{
if (subdirnum + 1 == subDirMaxNum)
{
subDirMaxNum *= 2;
Directory** temp = new Directory*[subDirMaxNum];
for (int i = 0; i < subdirnum; ++i)
temp[i] = subDir[i];
delete subDir;
subDir = temp;
}
Directory * d = this->getSubDir(dir->dirName);
if (d != NULL)
return -1; //目录已经存在;
subDir[subdirnum++] = dir;
}
void Directory::printDir() //显示目录信息
{
printf("\n");
int i;
for (i = 0; i < subdirnum; ++i)
printf("\t<DIR>\t\t%s\n", subDir[i]->dirName);
for (i = 0; i < filenum; ++i)
printf("\t<FILE>\t\t%s\n", filelist[i]->FileName);
}
Directory* Directory::getfatherDir() //获取父目录信息
{
return this->fatherDir;
}
Directory* Directory::getSubDir(const char* name) //获取子目录
{
int i;
for (i = 0; i < subdirnum; ++i)
{
if (0 == strcmp(subDir[i]->dirName, name))
return subDir[i];
}
return NULL;
}
File* Directory::getFile(const char* name)//获取目录下的文件
{
int i;
for (i = 0; i < filenum; ++i)
{
if (0 == strcmp(filelist[i]->FileName, name))
return filelist[i];
}
return NULL;
}
int Directory::mkDir(const char* dirname)//新建目录
{
if (subdirnum + 1 == subDirMaxNum) //目录列表扩容
{
subDirMaxNum *= 2;
Directory** temp = new Directory*[subDirMaxNum];
for (int i = 0; i < subdirnum; ++i)
temp[i] = subDir[i];
delete subDir;
subDir = temp;
}
Directory * d = this->getSubDir(dirname);
if (d != NULL)
return -1; //目录已经存在;
subDir[subdirnum++] = new Directory(dirname,this);
return 0;
}
int Directory::createFile(const char* filename)//新建文件
{
if (filenum + 1 == fileMaxNum)
{
fileMaxNum *= 2;
File** temp = new File*[fileMaxNum];
for (int i = 0; i < fileMaxNum; ++i)
temp[i] = filelist[i];
delete filelist;
filelist = temp;
}
File* f = this->getFile(filename);
if (f != NULL)
return -1;//文件已存在
filelist[filenum++] = new File(filename);
return 0;
}
int Directory::delFile(const char* file)
{
File* f=getFile(file);
if (f == NULL)
return -1;//文件不存在
pdelFile(f);
--filenum;
return 0;
}
int Directory::delDir(const char* dir)
{
Directory* d = getSubDir(dir);
if (d == NULL)
return -1;//目录
pdelDir(d);
--subdirnum;
return 0;
}
void Directory::pdelFile(File* f)
{
f->~File();//调用File 的析构函数
}
void Directory::pdelDir(Directory* dir)
{
if (dir == NULL)
return;
int i;
for (i = 0; i < dir->filenum; ++i)//删除目录下文件
pdelFile(dir->filelist[i]);
delete dir->filelist;
for (i = 0; i < dir->subdirnum; ++i)//递归删除子目录
pdelDir(dir->subDir[i]);
delete dir->subDir;//删除目录
}
Directory* getDirectory(vector<string> path, Directory* dir)//获取目录路径
{
int i;
for (i = 0; i < path.size(); ++i)
{
if (path[i] == ".")
dir = dir;
else if (path[i] == "..")
{
if( dir->getfatherDir()==NULL)
return NULL;
dir = dir->getfatherDir();
}
else
{
Directory* temp = dir->getSubDir(path[i].c_str());
if (temp == NULL)
return NULL;
dir = temp;
}
}
return dir;
}
File* getFile(vector<string>path, Directory* dir)//获取文件路径
{
string filename = path.back();
path.pop_back();
Directory* dstdir = getDirectory(path,dir);//先找到文件所在的目录
return dstdir->getFile(filename.c_str());//在目录下找到文件
}
FileManagementSystem.cpp
#include"pch.h"
#include<iostream>
#include <map>
#include<vector>
#include"File.h"
#include "Directory.h"
using namespace std;
#pragma warning(disable:4996)
map<string, string> OrderMessage; //记录相关指令的使用信息
map<string, string>up; //用户和密码
vector<string> currentPath;
Directory* root;
Directory* current;
//初始化程序
void initializeSystem();
//初步解析指令
void orderParsing(string &order, string &context);
//操作数解析
void contextParsing(string context, string &firstcontext, string &secondcontext);
//绝对路径解析
void pathParsing(vector<string> &path, string context);
//依据绝对路径找到当前目录
Directory* selectDirectory(vector<string> path);
//拷贝目录
void copyDir(string firstcontext, string secondcontext);
//新建目录
void mkDir(string context);
//void rnDir(vector<string> path, string Directoryname);
//删除目录
void delDir(string context);
//目录重命名
void rnDir(string path, string Directoryname);
//打印当前目录情况
void printDir();
//拷贝目录
void cpDir(string firstcontext, string secondcontext);
//返回上级
int cdReturn();
//进入目录
void cdPath(vector<string>path);
int cdNext(string context);
//创建文件
void createFile(string filename);
//删除文件
void deleteFile(string filename);
//重命名文件
void renameFile(string postname, string newname);
//复制文件
void copyFile(string firstcontext, string secondcontext);
//写文件
void writeFile(string filename);
//读文件
void readFile(string filename);
//显示帮助信息
void printHelp();
//清屏
void cleanPrinter();
int main()
{
initializeSystem();
cout << "Microsoft Windows [版本 10.0.17134.523]\n"
<< "(c)2018 Microsoft Corporation。保留所有权利。\n";
string order;
string context;
string firstcontext = "", secondcontext = "";
vector<string> path;
int i;
while (1)
{
//每次输入指令前自动换行
string path=currentPath[0];
for (i = 1; i < currentPath.size(); ++i)
path = path + '\\' + currentPath[i];
cout<<endl << path <<" $ ";
getline(cin, order);
orderParsing(order, context);
if (context.find_first_of(' ') != string::npos)
{
contextParsing(context, firstcontext, secondcontext);
}
if (order == "exit") //退出
{
break;
}
else if (order == "mkdir") //新建目录
{
if (context == "?")
{
cout << OrderMessage["mkdir"] << endl;
}
else if (context != "" && firstcontext == "")
{
mkDir(context);
//cout << currentlocal->catalogbother->catalogaddress << endl;
//cout << Memory[3] << endl;
}
else {
cout << OrderMessage["ordererror"] << endl;
}
}
else if (order == "deldir") //删除目录
{
if (context == "?")
{
cout << OrderMessage["deldir"] << endl;
}
else if (context == "")
{
cout << OrderMessage["ordererror"] << endl;
}
else if (firstcontext != "")
{
cout << OrderMessage["ordererror"] << endl;
}
else
{
delDir(context);
}
}
else if (order == "rndir") //目录重命名
{
if (context == "?")
{
cout << OrderMessage["rndir"] << endl;
}
else if (firstcontext == "")
{
cout << OrderMessage["ordererror"] << endl;
}
else
{
//pathParsing(path, firstcontext);
//rnDir(path, secondcontext);
//当前目录下
rnDir(firstcontext, secondcontext);
}
}
else if (order == "dir") //显示当前目录下的子目录
{
if (context == "?")
{
cout << OrderMessage["dir"] << endl;
}
else if (context != "")
{
cout << OrderMessage["ordererror"] << endl;
}
else
{
printDir();
}
}
else if (order == "cpdir") //目录拷贝
{
if (context == "?")
{
cout << OrderMessage["cpdir"] << endl;
}
else if (context == "" || firstcontext == "")
{
cout << OrderMessage["ordererror"] << endl;
}
else
{
copyDir(firstcontext, secondcontext);
}
}
else if (order == "cd")
{
if (context == "?")
{
cout << OrderMessage["cd"] << endl;
}
else if (context == "" || firstcontext != "")
{
cout << OrderMessage["ordererror"] << endl;
}
else
{
vector<string> content;
pathParsing(content, context);
cdPath(content);
}
}
else if (order == "create") //新建文件
{
if (context == "?")
{
cout << OrderMessage["create"] << endl;
}
else if (context == "" || firstcontext != "")
{
cout << OrderMessage["ordererror"] << endl;
}
else
{
createFile(context);
}
}
else if (order == "delete") //删除文件
{
if (context == "?")
{
cout << OrderMessage["delete"] << endl;
}
else if (context == "" || firstcontext != "")
{
cout << OrderMessage["ordererror"] << endl;
}
else
{
deleteFile(context);
}
}
else if (order == "rename") //文件重命名
{
if (context == "?")
{
cout << OrderMessage["rename"] << endl;
}
else if (firstcontext == "")
{
cout << OrderMessage["ordererror"] << endl;
}
else
{
renameFile(firstcontext, secondcontext);
}
}
else if (order == "copy") //文件拷贝
{
if (context == "?")
{
cout << OrderMessage["copy"] << endl;
}
else if (firstcontext == "")
{
cout << OrderMessage["ordererror"] << endl;
}
else
{
copyFile(firstcontext, secondcontext);
}
}
else if (order == "write") //读文件
{
if (context == "?")
{
cout << OrderMessage["write"] << endl;
}
else if (context == "" || firstcontext != "")
{
cout << OrderMessage["ordererror"] << endl;
}
else
{
writeFile(context);
}
}
else if (order == "read") //写文件
{
if (context == "?")
{
cout << OrderMessage["read"] << endl;
}
else if (context == "" || firstcontext != "")
{
cout << OrderMessage["ordererror"] << endl;
}
else
{
readFile(context);
}
}
else if (order == "help") //帮助命令
{
printHelp();
}
else if(order == "clean")//清屏
{
cleanPrinter();
}
else if(order =="")
{ }
else //错误指令
{
cout << "系统不存在该指令,请重新输入\n";
}
context = "";
firstcontext = "";
secondcontext = "";
}
return 0;
}
//初始化程序
void initializeSystem()
{
//帮助信息
OrderMessage["mkdir"] = string(3, ' ') + "[mkdir]:新建目录--mkdir dirname--dirname表示目录名";
OrderMessage["dir"] = "Hello";
OrderMessage["rndir"] = "rndir";
OrderMessage["ordererror"] = "指令使用格式错误";
//根目录初始化
root = new Directory("root",NULL);
currentPath.push_back(string(root->dirName));
current = root;
/*创建目录*/
root->mkDir("yay");
root->mkDir("lzr");
root->mkDir("guest");
/*创建用户*/
string psw = "123";
up.insert(pair<string, string>(string("yay"),psw));
up.insert(pair<string, string>(string("lzr"),psw));
up.insert(pair<string, string>(string("guest"), psw));
root->createFile("sys.ini");
/*登陆*/
bool flag = false;
while (true)
{
cout << endl << current->dirName << " $ ";
string order, context;
getline(cin, order);
orderParsing(order, context);
if (order == "cd")
{
if (!up.count(context))
cout << "没有该用户目录" << endl;
else
{
while (true)
{
cout << "password: ";
string p;
cin >> p;
if (up[context] == p)
{
cdNext(context);
flag = true;
system("cls");
break;
}
}
}
}
if (flag)
break;
}
}
//初步解析指令
void orderParsing(string &order, string &context)
{
if (order.size()<1)
return;
int notnull = order.find_last_not_of(' ');
//去除尾部空格
if (notnull != string::npos) {
order = order.substr(0, notnull + 1);
}
//去除首部空格
notnull = order.find_first_not_of(' ');
if (notnull != string::npos) {
order = order.substr(notnull, order.length() - notnull);
}
//寻找字串中第一个空格
int checkcontent = order.find_first_of(' ');
if (order[order.length() - 1] == '?')
{
//此时为指令+'?'形式
//将作为帮助指令处理
//去除最后一位
order = order.substr(0, order.length() - 1);
//反向查找第一个非空格的字符位置
notnull = order.find_last_not_of(' ');
if (notnull != string::npos)
{
//去除尾部空格,返回指令
order = order.substr(0, notnull + 1);
}
context = "?";
}
else if (checkcontent != string::npos)
{
//此时为指令+地址形式
//取出地址
context = order.substr(checkcontent + 1, order.length() - checkcontent - 1);
notnull = context.find_first_not_of(' ');
if (notnull != string::npos)
{
//去除首部空格
context = context.substr(notnull, context.length() - notnull);
}
order = order.substr(0, checkcontent);
}
else {
//此时为指令形式
context = "";
}
}
//操作数解析
void contextParsing(string context, string &firstcontext, string &secondcontext)
{
//找到两个操作数之间的空格连接符
int notnull = context.find_first_of(' ');
//取前一个操作数
firstcontext = context.substr(0, notnull);
//去除后一个操作数前的多余字符
notnull = context.find_last_of(' ');
//取出操作数
secondcontext = context.substr(notnull + 1, context.length() - notnull - 1);
}
//绝对路径解析
void pathParsing(vector<string> &path, string context)
{
if (path.empty() == false)
{
path.clear();
}
int lastsign = context.find_first_of('\\');
string pathtemp;
while (lastsign != string::npos)
{
pathtemp = context.substr(0, lastsign);
context = context.substr(lastsign + 1, context.length() - 1 - lastsign);
path.push_back(pathtemp);
lastsign = context.find_first_of('\\');
}
if (context != "")
{
path.push_back(context);
}
}
//依据绝对路径找到当前目录
Directory* selectDirectory(vector<string> path)
{
return NULL;
}
//新建目录
File* existFile(string filename);
void mkDir(string context)
{
current->mkDir(context.c_str());
}
void delDir(string context)
{
current->delDir(context.c_str());
}
//目录重命名
void rnDir(string path, string Directoryname)
{
Directory* d = current->getSubDir(path.c_str());
if (d == NULL)
{
cout << "目录不存在" << endl;
return;
}
d->reName(Directoryname.c_str());
}
//打印当前目录情况
void printDir()
{
current->printDir();
}
//返回上级
int cdReturn()
{
Directory* previous = current->getfatherDir();
if (previous == NULL)
{
cout << "已经是根目录了" << endl;
return -1;
}
current = previous;
currentPath.pop_back();
return 0;
}
//进入下级
int cdNext(string context)
{
Directory* next=current->getSubDir(context.c_str());
if (next == NULL)
{
cout << "此目录不存在" << endl;
return -1;
}
current = next;
currentPath.push_back(string(current->dirName));
return 0;
}
//创建文件
void createFile(string filename)
{
current->createFile(filename.c_str());
}
//删除文件
void deleteFile(string filename)
{
current->delFile(filename.c_str());
}
/*重命名文件*/
void renameFile(string postname, string newname)
{
File* f = current->getFile(postname.c_str());
if (f == NULL)
{
cout << "文件不存在" << endl;
return;
}
f->reName(newname.c_str());
}
/*复制文件*/
void copyFile(string firstcontext, string secondcontext)
{
vector<string>file;
vector<string>dir;
pathParsing(file, firstcontext);
pathParsing(dir, secondcontext);
Directory* dst = getDirectory(dir, current);
File* src = getFile(file, current);
if (dst == NULL)
cout << "目标目录不存在" << endl;
if(src ==NULL)
cout << "源文件不存在" << endl;
if(dst!=NULL&&src!=NULL)
dst->insertFile(src->copyFile());
}
/*复制目录*/
void copyDir(string firstcontext, string secondcontext)
{
vector<string>srcpath;
vector<string>dstpath;
pathParsing(srcpath, firstcontext);
pathParsing(dstpath, secondcontext);
//查找路径
Directory* src = getDirectory(srcpath, current);
Directory* dst = getDirectory(dstpath, current);
if (dst == NULL)
cout << "目标目录不存在" << endl;
if (src == NULL)
cout << "源目录不存在" << endl;
if (dst != NULL && src != NULL)
dst->insertDirectory(src->copyDirectory(dst));
}
/*写文件*/
void writeFile(string filename)
{
File* f = current->getFile(filename.c_str());
if (f == NULL)
{
cout << "文件不存在" << endl;
return;
}
string buffer;
while (1)
{
string bufferline;
getline(cin, bufferline);
if (bufferline == "quit")
break;
buffer += bufferline+'\n';
}
f->writeFile(buffer.c_str());
}
/*读文件*/
void readFile(string filename)
{
filename;
File* f = current->getFile(filename.c_str());
if (f == NULL)
{
cout << "文件不存在" << endl;
return;
}
const char* str = f->readFile();
if (str == NULL)
return;
cout << str << endl;
}
/*进入路径*/
void cdPath(vector<string>path)
{
int i;
Directory* copydir = current;
vector<string>savepath = currentPath;
int flag = 0;
for (i = 0; i < path.size(); ++i)
{
if (flag == -1)
break;
if (path[i] == "..")
flag = cdReturn();
else if (path[i] == ".")
;
else
{
flag =cdNext(path[i]);
}
}
if (flag == -1)
{
current = copydir;
currentPath = savepath;
}
}
/*帮助命令*/
void printHelp()
{
cout << "****** -- mkdir 新建目录 -- ******\n";
cout << "****** -- deldir 删除目录 -- ******\n";
cout << "****** -- rndir 目录重命名 -- ******\n";
cout << "****** -- dir 显示子目录 -- ******\n";
cout << "****** -- cpdir 目录拷贝 -- ******\n";
cout << "****** -- cd 转移当前目录 -- ******\n";
cout << "****** -- cd. 返回根目录 -- ******\n";
cout << "****** -- create 新建文件 -- ******\n";
cout << "****** -- delete 删除文件 -- ******\n";
cout << "****** -- rename 文件重命名 -- ******\n";
cout << "****** -- copy 文件拷贝 -- ******\n";
cout << "****** -- write 读取文件 -- ******\n";
cout << "****** -- read 写入文件 -- ******\n";
cout << "****** -- clean 清屏 -- ******\n";
cout << "****** -- exit 退出系统 -- ******\n";
}
//清屏
void cleanPrinter() {
system("cls");
cout << "Microsoft Windows [版本 10.0.17134.523]\n"
<< "(c)2018 Microsoft Corporation。保留所有权利。\n";
}
六、测试
6.1登录操作:输入用户名和密码即可登录,如图6.1所示
图6.1 登录过程
6.2帮助命令 登陆后,输入help命令即可查看命令列表。
图6.2 输出帮助
6.3创建目录mkdir 目录名
图6.3 创建目录
6.4删除目录
删除目录的命令 deldir + 目录的路径
图6.4 删除目录
6.5进入目录cd 相对路径
图6.5 进入目录
6.6目录重命名 rndir 原名称 修改名称
图6.6 目录重命名
6.7 目录拷贝 Cpdir 复制的目录路径 目的目录的路径
图6.7 拷贝目录
6.8创建文件 create + 文件名即可创建文件
图6.8 创建文件截图
6.9写入文件write + 文件名即可在该文件下写入内容,以quit作为结束
图6.9 写入文件
6.10读取文件 read + 文件名即可读取相应的文件
图6.10 读取文件
6.11文件重命名 rename + 文件名 + 文件新名即可对文件重命名
图6.11 文件重命名
6.12删除文件 delete + 文件名即可删除该文件
图6.12删除文件
6.13复制文件cpdir 源文件路径 目标文件路径
图6.13 复制文件
七、总结
同学一总结:
这次操作系统的课程设计是一次对操作系统的算法知识和编程实践能力的一次良好的锻炼。在课程设计中,我认为相比于编程,更为困难的是数据结构和算法的设计。目录和文件这样的数据结构,需要包含怎么样的信息,决定了这个系统功能的上限。数据结构之间如何组织,如何提升性能。文件和目录在磁盘上应该如何保存。这些问题都应该在进行课程设计之初耗费了许多精力。然后就是系统应该给外部提供怎样的命令接口。
这次实验应用了软件工程的思想,在编程之初先进行了详细的设计。使得在后期开发的时候,编码实现容易了很多。进行功能开发,只需要将几个函数功能组合起来进行了。在编程阶段遇到的主要问题是,没有设计好异常处理的问题。就是,我调用的时候返回了一个空指针但我没有去处理,于是就直接把空指针传参了,这个算是程序开发过程中的一个主要的bug。
这次实验加深了对于文件系统的理解,但是还是有很多不足之处。仅仅实现了比较简单的功能。没有能够实现那些更加复杂的机制。比如实现权限控制,用户管理这些操作。
同学二总结:
在本次设计中,我个人认为花费时间比较多的应该是数据结构的设计与更改。在开始时我们虽然做了较为详细的设计,但是,在接下来的开发中,我们发现太多的细节考虑不周,这些细节的失败直接导致了我们需要对文件系统的数据结构进行第二次设计,浪费了大量时间与经历,经过这次教训,我觉得以后再设计程序之前就应该考虑到具体的数据结构与项目实现之间的关系,尽量想得全面一点,这样利于后面的开发与实现。设计了一个比较满意的数据结构,本课程设计的实现就容易多了,但是某些操作还是需要取舍的,毕竟时间也有限
课程设计对编程能力肯定是一个不错的锻炼。在设计删除函数和操作函数时,原先我是设计为void型的,但是调试的时候发现删除根结点(第一个文件)的时候程序会出错。后来断点检查发现传地址的函数中,其传递的地址不可以在子函数中free掉,这样它的主函数中的地址也会被发生改变的,后来想到了给函数返回一个新的地址。
本次实验加深了我对文件的存储结构的理解,同时还锻炼了C++语言及其数据结构。