一、实验原理阐述
本实验意在基于散列(Hash),运用C++编写exe文件(后称云盘.exe)实现云盘上传、下载、查看云盘内容、删除文件的功能。特别的,运用散列实现上传的秒传。根据实验目的,做出以下实验设计。
一、云盘的结构。云盘主要有两部分,一部分是客户端,一部分是云端。客户端储存文件信息需要一个哈希表(hashtable,散列表,下称哈希表),客户端在使用时访问云端的哈希表,而客户端本身也是一种哈希表。因此本实验的客户端用哈希表模拟。云端用电脑中指定的一个文件夹模拟(本程序指定“D:\云盘”文件夹模拟,因此要求测试者在测试前在D盘创建一个名为“云盘”的文件夹。)。客户端用于操作,上传、下载、查看云盘文件内容、删除文件等,对象是许多个人。但是云端则由许多个人通过客户端传送的文件的汇总。一方面,当个人在客户端删除文件时,云端的文件不会受到影响。另一方面,每个人再上传文件的时候,根据云盘中的文件的hash值,区分上传的状态,“普通上传”或“秒传”。下面主要讨论云盘上传原理。
二、云盘的上传。云盘的上传分为“普通上传”和“秒传”,如果在云端不存在同样内容的文件,则为“普通上传”,需要花费上传时间。如果在云端存在同样内容的文件,则为“秒传”,不需要花费传送时间。根据这个特点,结合散列表的性质,可以知道文件上传之后信息会储存在哈希表中,每个文件经过一个hash函数,得出一个对于这个内容独特的hash值。每个上传的文件的内容也会经过同样的hash函数计算求出它的hash值,并查看散列表对应hash值的空间是否已被占用,若被占用,说明云端上已存在可能文件名不一样而内容一样的文件,则无需再花费时间上传,故实现“秒传”,然后在客户端记录上传资料的信息。本实验用电脑的“复制文件”功能模拟打开云盘客户端上传文件到云端的操作。而C++自身代码是不能够完成对电脑的文件复制转移功能的,因此需要调用cmd。
三、云盘的下载。本实验用将文件从“云端”(文件夹“D:\云盘”)复制要下载的文件到“下载目录”(由测试者指定的目录)来实现云盘的下载功能。同样需要调用cmd。
四、查看云盘中的文件。在“云盘.exe”中输出上传的。
五、删除云盘中的文件。原理上说,删除客户端中的文件是不会影响到云端的文件的,因此只是将要删除的指定文件夹的信息从客户端的哈希表中删除。
根据以上实验设计,下面使用代码实现模拟云盘。
二、代码实现
1.首先构造哈希表的类:
#include<iostream>
#include<vector>
#include<fstream>
#include<algorithm>
#include<string>
#include<Windows.h>
#include<cstddef>
using namespace std;
template<typename HashedObj>
class HashTable
{
public:
HashTable( int size = 101 )
{
currentSize = size;
vector< vector<HashedObj> > theLists( currentSize );
this -> theLists = theLists;
};//构造函数
bool contains( const HashedObj & x ) const;
void makeEmpty();
bool insert( HashedObj x, HashedObj path );
bool insert( HashedObj x );
int getsize();
bool remove( const HashedObj & x );
bool isEmpty( const HashedObj & x );
void loadcloud();
void upload();
void download();
void viewfile();
void exit();
void deletefile();
private:
vector< vector < HashedObj > > theLists;
int currentSize;
int hash( HashedObj x ) ;
};
2.各函数的实现:
判断是否包含内容 ( contains函数 ):
包含则返回1,不包含则返回0;
template <typename HashedObj> bool HashTable<HashedObj>::contains(const HashedObj &x) const
{
const vector<HashedObj> &whichList = theLists[myhash(x,theLists.size())];
return find( whichList.begin(), whichList.end(), x ) != whichList.end();
}
- 清空所有链表 ( makeEmpty函数 ):
template <typename HashedObj> void HashTable<HashedObj>::makeEmpty()
{
int size0 = theLists.size();
for(int i=0;i<size0;i++)
{
theLists[i].clear();
}
cout<<"已清空云盘"<<e