【C++】基于linux文件管理和C++的I/O框架,实现命令行下的文件管理器

时间:2021-09-03 14:54:55

一、实验项目内容

1、实现文件夹创建、删除、进入。
2、实现当前文件夹下的内容罗列。
3、实现文件拷贝和文件夹拷贝(文件夹拷贝指深度拷贝,包括所有子目录和文件)。

二、实验过程或算法

DocumentManger.h

#ifndef CIRCLE_H
#define CIRCLE_H

#include<stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include<sstream>
#include<iostream>
#include <dirent.h>
#include <fstream>
using namespace std;

class DocumentManager {                         //DocumentManger 文件管理类

private:
    char *path;
    char *newpath;
public:
    DocumentManager();                         //构造函数1
    DocumentManager( char *path);              //构造函数2

    void setNewpath( char* newpath);
    void setPath( char* path);
    void displayTips();                            //命令提示行

    int make_dir(const char *path, mode_t mode);   //创建文件夹
    int change_dir(const char *path);              //改变路径
    int remove_dir(const char* path);              //移除文件夹
    int get_file_size_time(const char *filename);  //获取文件的信息
    DIR * open_dir(const char *path);              //打开文件夹
    void read_dir(const char *path, bool ListAllFiles);    //读取文件夹
    int copy_dir(const char *filename, const char *newfilename);   //拷贝文件夹

};

#endif

DocumentManager.cpp

#include "DocumentManager.h"

DocumentManager::DocumentManager() {
    this->path = NULL;
}
DocumentManager::DocumentManager(char *path) {
    this->path = path;
}


void DocumentManager::setNewpath(char* newpath) {
    this->newpath = newpath;
}

void DocumentManager::setPath(char* path) {           //store this current path
    this->path = path;
}

void DocumentManager::displayTips() {                 //display these tips
    cout << "please input commands as the following: " << endl;
    cout << "0.mkdir [path]" << endl;
    cout << "1.chdir [path]" << endl;
    cout << "2.rmdir [path]" << endl;
    cout << "3.opendir [path]" << endl;
    cout << "4.readdir [path]" << endl;
    cout << "5.lldir [path]" << endl;
    cout << "5.copy [path] [newPath]" << endl;
    cout << "7.exit" << endl;
}

int DocumentManager::make_dir(const char *path, mode_t mode){
    if (mkdir(path,mode) != 0) {                       //make dir with mode
        cerr << "make dir fail" << endl;
    } else {
        cout << "make dir success" << endl;
    }
    return 0;
}
int DocumentManager::get_file_size_time(const char *filename)
{
    struct stat statbuf;                               //get the informations of file
    if (stat(filename, &statbuf) == -1) {
        cerr << "Get stat on" << filename << " Error: " << endl;
        cerr << strerror(errno) << endl;
    }
    if (S_ISDIR(statbuf.st_mode)) {
    }
    if (S_ISREG(statbuf.st_mode)) {
        cout << filename << " size:" << statbuf.st_size << " bytes"
                << " modified at " << ctime(&statbuf.st_mtime) << endl;
    }

    return 0;

}
int DocumentManager::change_dir(const char *path ){   //change the dir
    this->path=(char*)path;

    if (chdir(path) != 0) {
        cout << "change dir fail" << endl;
    } else {
        cout << "change dir success" << endl;
    }
    return 0;
}

int DocumentManager::remove_dir(const char* path){    //remove dir
    DIR *dirp=opendir(path);
    if(dirp==NULL){                                   //打开文件夹失败
        perror(path);                                 //输出错误的原因
        return 0;
    }
    struct dirent *entry;
    int ret;
    while (1) {
        entry = readdir(dirp);
        if (entry == NULL) {                          //若父目录为空,直接退出循环
            break;
        }
        if(strcmp(".",entry->d_name)==0||strcmp("..",entry->d_name)==0){
            continue;
        }
        char buf[80];
        snprintf(buf,80,"%s/%s",path,entry->d_name);  //重构子目录
        ret=remove(buf);                              //delete these files
        if(ret==-1){
            if(errno==ENOTEMPTY){                     //删除失败
                remove_dir(buf);
                continue;
            }
            perror(buf);                              //输出失败的原因
            return 0;
        }

    }

    closedir(dirp);
    ret=rmdir(path);                                  //delete the empty dir
    if(ret==-1){
        perror(path);
    }
    else{
        cout<<"remove dir success!"<<endl;
    }
    return 0;
}

DIR * DocumentManager::open_dir(const char *path) {
    DIR *dirp=opendir(path);                          //open the dir
    if (dirp!= NULL) {
        cout << "open dir success" << endl;
    }
    else{
        cerr<<"Open Directory"<<path<<" Error: "<<endl;
        cerr<<strerror(errno)<<endl;
    }
    closedir(dirp);                                    //closedir
    return dirp;
}

void DocumentManager::read_dir(const char *path,bool JustListFileName)
{
    DIR *dirp=opendir(path);
    struct dirent *direntp;
    static char dot[] = ".", dotdot[] = "..";
    char buf[80];
    while ((direntp = readdir(dirp)) != NULL) {
        if (strcmp(direntp->d_name, dot) && strcmp(direntp->d_name, dotdot)) {
            if (JustListFileName) {                  //just read the filename
                cout << direntp->d_name << endl;
            } else {
                sprintf(buf, "%s/%s", path, direntp->d_name);
                if (get_file_size_time(buf) == -1)          //get the information
                    break;
            }
        }
    }
    closedir(dirp);                                 //closedir
}



int DocumentManager::copy_dir(const char *filename, const char *newfilename) {
    struct stat cur_file;
    stat(filename, &cur_file);

    if (S_ISDIR(cur_file.st_mode)) {               //路径是文件夹
        DIR *cur_dir;
        dirent *cur_ent;
        int errnum = 0;

        if ((cur_dir = opendir(filename)) == NULL){
            return 1;
        }
        if (access(newfilename, F_OK)){          //文件夹不存在,创建这个目标文件夹
            errnum |= mkdir(newfilename, S_IRWXU);
        }
        while ((cur_ent = readdir(cur_dir)) != NULL)    //递归,复制子目录
            if (strcmp(cur_ent->d_name, ".") && strcmp(cur_ent->d_name, "..")) {
                errnum |= copy_dir(((string)filename + "/" + cur_ent->d_name).c_str(),
                        ((string)newfilename + "/" + cur_ent->d_name).c_str());
            }
        closedir(cur_dir);                       //close dir
        return errnum;
    } else {                                    //路径是文件名
        if (filename == newfilename){           //若两个路径相同则视为无效,退出
            return 0;
        }
        fstream fsin, fsout;                   //拷贝文件
        fsin.open(filename,ios::in | ios::binary);
        fsout.open(newfilename, ios::out |ios::binary);
        fsout << fsin.rdbuf();
        return 1;
    }
}

DocumenManger的测试类:

#include "DocumentManager.h"
#include<stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include<sstream>
#include<iostream>
#include <dirent.h>
#include <fstream>
using namespace std;

int main(){

    DocumentManager documentmanger;              //declare a DocumentManager

    documentmanger.displayTips();                //outputs the tips

    string input, command, path, newPath;
    int i;
    while (getline(cin, input)) {
        istringstream is(input);
        string s;                                //deal this inputs
        for (i = 0; is >> s; i++) {
            if (s.compare("exit") == 0) {        //command is exit
                exit(0);
            }
        }
        if (i != 2 & i != 3) {
            cerr << "your input is Illegal" << endl;
            continue;
        }
        istringstream temp(input);
        temp >> command >> path >> newPath;

        if (command.compare("mkdir") == 0) {     //command is mkdir
            const char* pa = path.c_str();
            documentmanger.make_dir(pa, 0755);
        }
        else if (command.compare("chdir") == 0) {//command is chdir
            const char* pa = path.c_str();
            documentmanger.change_dir(pa);

        }
        else if (command.compare("rmdir") == 0) {//command is rmdir
            const char* pa = path.c_str();
            documentmanger.remove_dir((char* )pa);
        }
        else if (command.compare("opendir") == 0) {//command is opendir
            const char* pa = path.c_str();
            documentmanger.open_dir((pa));
        }
        else if (command.compare("readdir") == 0) {//command is readdir
            const char* pa = path.c_str();
            documentmanger.read_dir(pa,1);
        }
        else if (command.compare("lldir") == 0) {//command is lldir
            const char* pa = path.c_str();
            documentmanger.read_dir(pa,0);
        }
        else if (command.compare("copy") == 0) { //command is copy
            const char* pa = path.c_str();
            const char* npa = newPath.c_str();
            documentmanger.copy_dir(pa, npa);
        }
    }
    return 0;
}

三、实验结果和截图

【C++】基于linux文件管理和C++的I/O框架,实现命令行下的文件管理器
【C++】基于linux文件管理和C++的I/O框架,实现命令行下的文件管理器
【C++】基于linux文件管理和C++的I/O框架,实现命令行下的文件管理器
【C++】基于linux文件管理和C++的I/O框架,实现命令行下的文件管理器
【C++】基于linux文件管理和C++的I/O框架,实现命令行下的文件管理器