• 云备份客户端——客户端整体设计框架以及实用类工具实现


     一,客户端整体框架

    客户端要实现的功能和服务端相比相对简单,客户端要实现的功能是自动对指定文件中的文件进行备份,也就是定时对指定文件进行扫描,根据文件信息判断文件,符合要求(新文件或者被修改过的文件)进行上传

    因此我们客户端大概需要实现下面三个模块

    • 数据管理模块:管理备份文件的文件信息,后续需要通过该信息判断文件是否上传
    • 目录遍历模块:定时遍历指定文件下的所有文件
    • 文件备份模块:遍历文件时,根据文件信息判断是否上传

     开发环境

     由于我们客户端大多是给windows用户使用的,因此客户端在Windows上用vs2019进行开发

    二,实用工具类实现

    客户端的实用工具类的实现和服务端是一样的,但是功能少了些,例如压缩解压缩,同时因为vs2019上按照Json库不太方便,因此Json序列化和Json反序列化也不在使用,而在数据管理模块中数据存储时用到的序列化和反序列化,由我们自己完成。

    1. #ifndef _MY_UTIL_
    2. #define _MY_UTIL_
    3. #define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING 1
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. namespace mjw_cloud
    13. {
    14. namespace fs=std::experimental::filesystem;
    15. class FileUtil
    16. {
    17. public:
    18. FileUtil(const std::string &filename)
    19. : _filename(filename)
    20. {
    21. }
    22. // 获取文件大小
    23. size_t FileSize()
    24. {
    25. struct stat st;
    26. if (stat(_filename.c_str(), &st) < 0)
    27. {
    28. std::cout << "get file attributes failed" << std::endl;
    29. return -1;
    30. }
    31. return st.st_size;
    32. }
    33. // 获取文件最后一次修改时间&最后一次访问时间
    34. time_t LastMTime()
    35. {
    36. struct stat st;
    37. if (stat(_filename.c_str(), &st) < 0)
    38. {
    39. std::cout << "get file attributes failed" << std::endl;
    40. return -1;
    41. }
    42. return st.st_mtime;
    43. }
    44. time_t LastATime()
    45. {
    46. struct stat st;
    47. if (stat(_filename.c_str(), &st) < 0)
    48. {
    49. std::cout << "get file attributes failed" << std::endl;
    50. return -1;
    51. }
    52. return st.st_atime;
    53. }
    54. // 获取文件路径名中的文件名
    55. //./abc/test.c ->test.c
    56. std::string FileName()
    57. {
    58. //这里由于时Windows下,因此目录符号需要改变
    59. /*int pos = _filename.find_last_of("/");*/
    60. int pos = _filename.find_last_of("\\");
    61. if (pos < 0)
    62. {
    63. if(!_filename.empty()) return _filename;
    64. std::cout << "filename error" << std::endl;
    65. return nullptr;
    66. }
    67. return _filename.substr(pos + 1);
    68. }
    69. // 获取文件指定位置指定长度字符串
    70. bool GetPosLen(std::string *body, size_t pos, size_t len)
    71. {
    72. std::ifstream ifs(_filename, std::ios::binary);
    73. if (ifs.is_open() == false)
    74. {
    75. std::cout << "open file failed" << std::endl;
    76. return false;
    77. }
    78. size_t size = this->FileSize();
    79. if (pos + len > size)
    80. {
    81. std::cout << "Get filecontent is be illegal" << std::endl;
    82. return false;
    83. }
    84. ifs.seekg(pos, ifs.beg);
    85. body->resize(size);
    86. ifs.read(&(*body)[0], len);
    87. if (ifs.good() == false)
    88. {
    89. std::cout << "read file failed" << std::endl;
    90. return false;
    91. }
    92. ifs.close();
    93. return true;
    94. }
    95. // 向文件写入数据&向文件读取数据
    96. bool SetContent(const std::string &body)
    97. {
    98. std::ofstream ofs(_filename, std::ios::binary);
    99. if (ofs.is_open() == false)
    100. {
    101. std::cout << "SetContent open file failed" << std::endl;
    102. return false;
    103. }
    104. ofs.write(&body[0], body.size());
    105. if (ofs.good() == false)
    106. {
    107. std::cout << "write file failed" << std::endl;
    108. return false;
    109. }
    110. ofs.close();
    111. return true;
    112. }
    113. bool GetContent(std::string *body)
    114. {
    115. size_t fsize = this->FileSize();
    116. return GetPosLen(body, 0, fsize);
    117. }
    118. // 判断文件是否存在
    119. bool Exists()
    120. {
    121. struct stat sm;
    122. return stat(_filename.c_str(), &sm) == 0;
    123. }
    124. // 创建文件目录&获取文件目录
    125. bool CreateDirectory()
    126. {
    127. if(Exists()) return true;
    128. return fs::create_directories(_filename);
    129. }
    130. bool ScanDirectory(std::vector* arry)
    131. {
    132. CreateDirectory();
    133. for (auto &i : fs::directory_iterator(_filename))
    134. {
    135. if(fs::is_directory(i)==true)//如果文件是路径名则跳过
    136. {
    137. continue;
    138. }
    139. arry->push_back(fs::path(i).relative_path().string());
    140. }
    141. return true;
    142. }
    143. bool Remove()
    144. {
    145. if (Exists() == false)
    146. {
    147. std::cout << "object file unexist" << std::endl;
    148. return false;
    149. }
    150. remove(_filename.c_str());
    151. return true;
    152. }
    153. private:
    154. std::string _filename;
    155. };
    156. }
    157. #endif

     

     

  • 相关阅读:
    MyBatis学习:使用占位符#
    零跑C01用低配车型教BBA重新诠释智能与豪华
    加密和验签
    区块链、以太坊,以太坊和智能合约
    数据可视化,销量第一的新能源汽车是什么?比亚迪新能源汽车销量接近60万辆
    网路系统规划与设计(CCNA)复习纲要 第一部分:网络通识基础
    数据库压力测试方法小结
    联盛德W801系列8-编译链接时找不到标准数学库函数的解决方法
    Java泛型的总结
    “智”造未来,江西同为科技(TOWE)参展第四届广州“两交会”圆满落幕
  • 原文地址:https://blog.csdn.net/zcxmjw/article/details/132744722