云备份项目

2023-11-11

云备份项目

1. 云备份认识

自动将本地计算机上指定文件夹中需要备份的文件上传备份到服务器中。并且能够随时通过浏览器进行查看并且下载,其中下载过程支持断点续传功能,而服务器也会对上传文件进行热点管理,将非热点文件进行压缩存储,节省磁盘空间。

2. 实现目标

这个云备份项目需要我们实现两端程序,其中包括部署在用户机的客户端程序,上传需要备份的文件,以及运行在服务器上的服务端程序,实现备份文件的存储和管理,两端合作实现总体的自动云备份功能。

3. 功能划分

3.1 服务端

3.1.1 服务端程序负责功能
  • 针对客户端上传的文件进行备份存储
  • 能够对文件进行热点文件管理,对非热点文件进行压缩存储,节省磁盘空间。
  • 支持客户端浏览器查看访问文件列表。
  • 支持客户端浏览器下载文件,并且下载支持断点续传。
3.1.2. 服务端功能模块划分
  • 数据管理模块:负责服务器上备份文件的信息管理。
  • 网络通信模块:搭建网络通信服务器,实现与客户端通信。
  • 业务处理模块:针对客户端的各个请求进行对应业务处理并响应结果。
  • 热点管理模块:负责文件的热点判断,以及非热点文件的压缩存储。

3.2 客户端

3.2.1 客户端程序负责功能
  • 能够自动检测客户机指定文件夹中的文件,并判断是否需要备份
  • 将需要备份的文件逐个上传到服务器
3.2.2 客户端功能模块划分
  • 数据管理模块:负责客户端备份的文件信息管理,通过这些数据可以确定一个文件是否需要备份。
  • 文件检测模块:遍历获取指定文件夹中所有文件路径名称。
  • 网络通信模块:搭建网络通信客户端,实现将文件数据备份上传到服务器。

4. 第三方库

4.1 jsoncpp

json是一种数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据。

json数据类型:对象:使用花括号{}括起来的表示一个对象。数组:使用中括号[]括起来的表示一个数组。字符串:使用常规双引号""括起来的表示一个字符串。数字:包括整形和浮点型,直接使用。

例如:小明同学的学生信息

char name = "小明";
int age = 18;
float score[3] = {88.5, 99, 58};
则json这种数据交换格式是将这多种数据对象组织成为一个字符串:
[
    {
        "姓名" : "小明",
        "年龄" : 18,
        "成绩" : [88.5, 99, 58]
    },
    {
        "姓名" : "小黑",
        "年龄" : 18,
        "成绩" : [88.5, 99, 58]
    }
]

jsoncpp库用于实现json格式的序列化和反序列化,完成将多个数据对象组织成为json格式字符串,以及将json格式字符串解析得到多个数据对象的功能。

这其中主要借助三个类以及其对应的少量成员函数完成:

//Json数据对象类
class Json::Value{
    Value &operator=(const Value &other); //Value重载了[]和=,因此所有的赋值和获取数据都可以通过
    Value& operator[](const std::string& key);//简单的方式完成 val["姓名"] = "小明";
    Value& operator[](const char* key);
    Value removeMember(const char* key);//移除元素
    const Value& operator[](ArrayIndex index) const; //val["成绩"][0]
    Value& append(const Value& value);//添加数组元素val["成绩"].append(88); 
    ArrayIndex size() const;//获取数组元素个数 val["成绩"].size();
    std::string asString() const;//转string 	 string name = val["name"].asString();
    const char* asCString() const;//转char*   char *name = val["name"].asCString();
    Int asInt() const;//转int				int age = val["age"].asInt();
    float asFloat() const;//转float
    bool asBool() const;//转 bool
};

//json序列化类,低版本用这个更简单
class JSON_API Writer {
  virtual std::string write(const Value& root) = 0;
}
class JSON_API FastWriter : public Writer {
  virtual std::string write(const Value& root);
}
class JSON_API StyledWriter : public Writer {
  virtual std::string write(const Value& root);
}
//json序列化类,高版本推荐,如果用低版本的接口可能会有警告
class JSON_API StreamWriter {
    virtual int write(Value const& root, std::ostream* sout) = 0;
}
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
    virtual StreamWriter* newStreamWriter() const;
}

//json反序列化类,低版本用起来更简单
class JSON_API Reader {
	bool parse(const std::string& document, Value& root, bool collectComments = true);
}
//json反序列化类,高版本更推荐
class JSON_API CharReader {
    virtual bool parse(char const* beginDoc, char const* endDoc, 
                       Value* root, std::string* errs) = 0;
}
class JSON_API CharReaderBuilder : public CharReader::Factory {
    virtual CharReader* newCharReader() const;
}

4.2 bundle数据压缩库

GitHub链接

BundleBundle是一个嵌入式压缩库,支持23种压缩算法和2种存档格式。使用的时候只需要加入两个文件bundle.hbundle.cpp即可。

namespace bundle
{
  // low level API (raw pointers)
  bool is_packed( *ptr, len );
  bool is_unpacked( *ptr, len );
  unsigned type_of( *ptr, len );
  size_t len( *ptr, len );
  size_t zlen( *ptr, len );
  const void *zptr( *ptr, len );
  bool pack( unsigned Q, *in, len, *out, &zlen );
  bool unpack( unsigned Q, *in, len, *out, &zlen );

  // medium level API, templates (in-place)
  bool is_packed( T );
  bool is_unpacked( T );
  unsigned type_of( T );
  size_t len( T );
  size_t zlen( T );
  const void *zptr( T );
  bool unpack( T &, T );
  bool pack( unsigned Q, T &, T );

  // high level API, templates (copy)
  T pack( unsigned Q, T );
  T unpack( T );
}

4.3. httplib库

GitHub链接

httplib库,一个C++11单文件头的跨平台HTTP/HTTPS库。安装起来非常容易。只需包含httplib.h在你的代码中即可。

httplib库实际上是用于搭建一个简单的http服务器或者客户端的库,这种第三方网络库,可以让我们免去搭建服务器或客户端的时间,把更多的精力投入到具体的业务处理中,提高开发效率。

namespace httplib{
    struct MultipartFormData {
        std::string name;
        std::string content;
        std::string filename;
        std::string content_type;
    };
    using MultipartFormDataItems = std::vector<MultipartFormData>;
    struct Request {
        std::string method;
        std::string path;
        Headers headers;
        std::string body;
        // for server
        std::string version;
        Params params;
        MultipartFormDataMap files;
        Ranges ranges;
        bool has_header(const char *key) const;
        std::string get_header_value(const char *key, size_t id = 0) const;
        void set_header(const char *key, const char *val);
        bool has_file(const char *key) const;
        MultipartFormData get_file_value(const char *key) const;
    };
    struct Response {
        std::string version;
        int status = -1;
        std::string reason;
        Headers headers;
        std::string body;
        std::string location; // Redirect location
		void set_header(const char *key, const char *val);
        void set_content(const std::string &s, const char *content_type);
    };
	class Server {
        using Handler = std::function<void(const Request &, Response &)>;
        using Handlers = std::vector<std::pair<std::regex, Handler>>;
        std::function<TaskQueue *(void)> new_task_queue;
        Server &Get(const std::string &pattern, Handler handler);
  		Server &Post(const std::string &pattern, Handler handler);
        Server &Put(const std::string &pattern, Handler handler);
  		Server &Patch(const std::string &pattern, Handler handler);  
  		Server &Delete(const std::string &pattern, Handler handler);
  		Server &Options(const std::string &pattern, Handler handler);
        bool listen(const char *host, int port, int socket_flags = 0);
	};
    class Client {
        Client(const std::string &host, int port);
  		Result Get(const char *path, const Headers &headers);
        Result Post(const char *path, const char *body, size_t content_length,
              const char *content_type);
        Result Post(const char *path, const MultipartFormDataItems &items);
    }
}

5. 服务端工具类实现

5.1 文件实用工具类设计

不管是客户端还是服务端,文件的传输备份都涉及到文件的读写,包括数据管理信息的持久化也是如此,因此首先设计封装文件操作类,这个类封装完毕之后,则在任意模块中对文件进行操作时都将变的简单化。

C++17中filesystem手册

/*util.hpp*/
class FileUtil{
	private:
    	std::string _name;
    public:
    	FileUtil(const std::string &name);
    	size_t FileSize();
    	time_t LastATime();
    	time_t LastMTime();
    	std::string FileName();
    	bool GetPosLen(std::string *content, size_t pos, size_t len);
    	bool GetContent(std::string *content);
    	bool SetContent(std::strint *content);
    	bool Compress(const std::string &packname);
    	bool UnCompress(const std::string &filename);
    	bool Exists();
    	bool CreateDirectory();
    	bool ScanDirectory(std::vector<std::string> *arry);
};

5.2 json实用工具类设计

/*util.hpp*/
class JsonUtil{
	public:
		static bool Serialize(const Json::Value &root, std::string *str);
    	static bool UnSerialize(const std::string &str, Json::Value *root);
};

6. 服务端配置信息模块实现

6.1 系统配置信息

使用文件配置加载一些程序的运行关键信息可以让程序的运行更加灵活。

配置信息:

  • 热点判断时间
  • 文件下载URL前缀路径
  • 压缩包后缀名称
  • 上传文件存放路径
  • 压缩文件存放路径
  • 服务端备份信息存放文件
  • 服务器访问IP地址
  • 服务器访问端口
{
    "hot_time" : 30,
    "server_port" : 8888,
    "server_ip" : "172.19.54.175",  
    "download_prefix" : "/download/",
    "packfile_suffix" : ".lz",
    "pack_dir" : "./packdir/",
    "back_dir" : "./backdir/",
    "backup_file" : "./cloud.dat"
}

6.2 单例文件配置类设计

使用单例模式管理系统配置信息,能够让配置信息的管理控制更加统一灵活。

#define CONFIG_FILE "./cloud.conf"
#ifndef __M_CONFIG_H__
#define __M_CONFIG_H__
#include <mutex>
#include "util.hpp"
namespace cloud
{
    class Config
    {
    private:
        Config(){}
        static Config *_instance;
        static std::mutex _mutex;
    private:
        int _hot_time;                // 热点判断时间
        int _server_port;             // 服务器监听端口
        std::string _server_ip;       // 服务器IP地址
        std::string _download_prefix; // 下载url前缀路径
        std::string _packfile_suffix; // 压缩包后缀名称
        std::string _pack_dir;        // 压缩包存放目录
        std::string _back_dir;        // 备份文件存放目录
        std::string _backup_file;     // 数据信息存放文件
        bool ReadConfigFile(){}
    public:
        static Config *GetInstance(){}
        int GetHotTime(){}
        int GetServerPort(){}
        std::string GetServerIP(){}
        std::string GetDownloadPrefix(){}
        std::string GetPackFileSuffix(){}
        std::string GetPackDir(){}
        std::string GetBackDir(){}
        std::string GetBackupFile(){}
    };
    Config *Config::_instance = nullptr;
    std::mutex Config::_mutex;
}
#endif

6.3 管理的数据信息

  • 文件实际存储路径
  • 文件是否压缩标志
  • 压缩包存储路径
  • 文件访问URL
  • 文件最后一次修改时间
  • 文件最后一次访问时间
  • 文件大小

6.4 如何管理数据

  • 内存中以文件访问URL为key,数据信息结构为val,使用哈希表进行管理,查询速度快。使用url作为key是因为往后客户端浏览器下载文件的时候总是以url作为请求。
  • 采用文件形式对数据进行持久化存储(序列化方式采用json格式或者自定义方式)

6.5 数据管理类的设计

/*data.hpp*/
#ifndef __M_DATA_H__
#define __M_DATA_H__
#include <unordered_map>
#include <pthread.h>
#include "util.hpp"
#include "config.hpp"
namespace cloud
{
    typedef struct BackupInfo
    {
        bool pack_flag;        // 是否压缩标志
        size_t fsize;          // 文件大小
        time_t atime;          // 最后一次访问时间
        time_t mtime;          // 最后一次更改时间
        std::string real_path; // 文件实际存储路径
        std::string pack_path; // 压缩文件储存路径
        std::string url_path;  //
        bool NewBackupInfo(const std::string &realpath){}     
    } BackupInfo;
    class DataManager
    {
    public:
        DataManager(){}
        ~DataManager(){} 
        bool Insert(const BackupInfo &info){}   
        bool Update(const BackupInfo &info){}    
        bool GetOneByURL(const std::string &url, BackupInfo *info){}
        bool GetOneByRealPath(const std::string &realpath, BackupInfo *info){}
        bool GetAll(std::vector<BackupInfo> *array){} 
        bool Storage(){}
        bool InitLoad(){}
    private:
        std::string _backup_file;
        pthread_rwlock_t _rwlock; // 读写锁 - 读共享,写互斥
        std::unordered_map<std::string, BackupInfo> _table;
    };
}
#endif

7. 服务端热点管理模块实现

7.1 热点管理实现思路

服务器端的热点文件管理是对上传的非热点文件进行压缩存储,节省磁盘空间。

而热点文件的判断在于上传的文件的最后一次访问时间是否在热点判断时间之内,比如如果一个文件一天都没有被访问过我们就认为这是一个非热点文件,其实就是当前系统时间,与文件最后一次访问时间之间的时间差是否在一天之内的判断。

而我们需要对上传的文件每隔一段时间进行热点检测,相当于遍历上传文件的存储文件夹,找出所有的文件,然后通过对逐个文件进行时间差的判断,来逐个进行热点处理。

基于这个思想,我们需要将上传的文件存储位置与压缩后压缩文件的存储位置分开。这样在遍历上传文件夹的时候不至于将压缩过的文件又进行非热点处理了。

关键点:

  • 上传文件有自己的上传存储位置,非热点文件的压缩存储有自己的存储位置
  • 遍历上传存储位置文件夹,获取所有文件信息。
  • 获取每个文件最后一次访问时间,进而完成是否热点文件的判断。
  • 对非热点文件进行压缩存储,删除原来的未压缩文件。

7.2 热点管理类的设计

#ifndef __M_HOT_H__
#define __M_HOT_H__
#include <unistd.h>
#include "data.hpp"
//因为数据管理是要在多个模块中访问的,因此将其作为全局数据定义,在此处声明使用即可
extern cloud::DataManager *_data;
namespace cloud
{
    class HotManager
    {
    public:
        HotManager(){}
        bool RunModule(){}     
    private:
        // 非热点文件-假    热点文件-真
        bool HotJudge(const std::string &filename){}
    private:
        std::string _back_dir;
        std::string _pack_dir;
        std::string _pack_suffix;
        int _hot_time;
    };
}
#endif

8. 服务端业务处理模块实现

8.1 业务处理实现思路

云备份项目中 ,业务处理模块是针对客户端的业务请求进行处理,并最终给与响应。而整个过程中包含以下要实现的功能:

  • 借助网络通信模块httplib库搭建http服务器与客户端进行网络通信
  • 针对收到的请求进行对应的业务处理并进行响应(文件上传,列表查看,文件下载(包含断点续传))

8.2 网络通信接口设计

业务处理模块要对客户端的请求进行处理,那么我们就需要提前定义好客户端与服务端的通信,明确客户端发送什么样的请求,服务端处理后应该给与什么样的响应,而这就是网络通信接口的设计。

HTTP文件上传:

POST /upload HTTP/1.1
Content-Length:11
Content-Type:multipart/form-data;boundary= ----WebKitFormBoundary+16字节随机字符
------WebKitFormBoundary
Content-Disposition:form-data;filename="a.txt";
hello world
------WebKitFormBoundary--
HTTP/1.1 200 OK
Content-Length: 0

HTTP文件列表获取:

GET /list HTTP/1.1
Content-Length: 0
HTTP/1.1 200 OK
Content-Length: 
Content-Type: text/html

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  	<title>Page of Download</title>
  </head>
  <body>
  	<h1>Download</h1>
  	<table>
  	  <tr>
  	    <td><a href="/download/a.txt"> a.txt </a></td>
  	    <td align="right"> 1994-07-08 03:00 </td>
  	    <td align="right"> 27K </td>
  	  </tr>
  	</table>
  </body>
</html>

HTTP文件下载:

GET /download/a.txt http/1.1
Content-Length: 0
HTTP/1.1 200 OK
Content-Length: 100000
ETags: "filename-size-mtime一个能够唯一标识文件的数据"
Accept-Ranges: bytes

文件数据

HTTP断点续传:

GET /download/a.txt http/1.1
Content-Length: 0
If-Range: "文件唯一标识"
Range: bytes=89-999
HTTP/1.1 206 Partial Content
Content-Length: 
Content-Range: bytes 89-999/100000
Content-Type: application/octet-stream
ETag: "inode-size-mtime一个能够唯一标识文件的数据"
Accept-Ranges: bytes

对应文件从89到999字节的数据。

8.3 业务处理类设计

//因为业务处理的回调函数没有传入参数的地方,因此无法直接访问外部的数据管理模块数据
//可以使用lamda表达式解决,但是所有的业务功能都要在一个函数内实现,于功能划分上模块不够清晰
//因此将数据管理模块的对象定义为全局数据,在这里声明一下,就可以在任意位置访问了
#ifndef __M_SERVICE_H__
#define __M_SERVICE_H__
#include <sstream>
#include "data.hpp"
#include "httplib.h"
extern cloud::DataManager *_data;
namespace cloud
{
    class Service
    {
    public:
        Service(){}        
        bool RunModule(){}       
    private:
        static void Upload(const httplib::Request &req, httplib::Response &rsp){}        
        // 静态成员函数不能调用非静态成员函数 -- 没有this指针
        static std::string TimetoStr(time_t t){}        
        static void ListShow(const httplib::Request &req, httplib::Response &rsp){} 
        static std::string GetETag(const BackupInfo &info){}     
        static void Download(const httplib::Request &req, httplib::Response &rsp){}
    private:
        std::string _server_ip;       // IP地址
        int _server_port;             // 端口号
        std::string _download_prefix; // 下载前缀
        httplib::Server _server;      // http对象
    };
}
#endif

9. 客户端数据管理模块实现

9.1 数据信息设计

客户端要实现的功能是对指定文件夹中的文件自动进行备份上传。但是并不是所有的文件每次都需要上传,我们需要能够判断,哪些文件需要上传,哪些不需要,因此需要将备份的文件信息给管理起来,作为下一次文件是否需要备份的判断。因此需要被管理的信息包含以下:

  • 文件路径名称
  • 文件唯一标识:由文件名,最后一次修改时间,文件大小组成的一串信息

9.2 文件操作实用类设计

这个其实与服务端的文件实用工具类雷同,只是功能需求并没有服务端那么多。

#ifndef __M_SERVICE_H__
#define __M_SERVICE_H__
#include <sstream>
#include "data.hpp"
#include "httplib.h"
extern cloud::DataManager *_data;
namespace cloud
{
    class Service
    {
    public:
        Service(){}    
        bool RunModule(){}
    private:
        static void Upload(const httplib::Request &req, httplib::Response &rsp){}
        // 静态成员函数不能调用非静态成员函数 -- 没有this指针
        static std::string TimetoStr(time_t t){}     
        static void ListShow(const httplib::Request &req, httplib::Response &rsp){}
        static std::string GetETag(const BackupInfo &info){}
        static void Download(const httplib::Request &req, httplib::Response &rsp){}
    private:
        std::string _server_ip;       // IP地址
        int _server_port;             // 端口号
        std::string _download_prefix; // 下载前缀
        httplib::Server _server;      // http对象
    };
}
#endif

9.3 数据管理类设计

#ifndef __M_SERVICE_H__
#define __M_SERVICE_H__
#include <sstream>
#include "data.hpp"
#include "httplib.h"
extern cloud::DataManager *_data;
namespace cloud
{
    class Service
    {
    public:
        Service(){}        
        bool RunModule(){}       
    private:
        static void Upload(const httplib::Request &req, httplib::Response &rsp){}
        // 静态成员函数不能调用非静态成员函数 -- 没有this指针
        static std::string TimetoStr(time_t t)
        static void ListShow(const httplib::Request &req, httplib::Response &rsp){}
        static std::string GetETag(const BackupInfo &info){}    
        static void Download(const httplib::Request &req, httplib::Response &rsp){}
    private:
        std::string _server_ip;       // IP地址
        int _server_port;             // 端口号
        std::string _download_prefix; // 下载前缀
        httplib::Server _server;      // http对象
    };
}
#endif

9.4 文件备份类设计

#ifndef __M_SERVICE_H__
#define __M_SERVICE_H__
#include <sstream>
#include "data.hpp"
#include "httplib.h"
extern cloud::DataManager *_data;
namespace cloud
{
    class Service
    {
    public:
        Service(){}
        bool RunModule(){}
    private:
        static void Upload(const httplib::Request &req, httplib::Response &rsp){}
        // 静态成员函数不能调用非静态成员函数 -- 没有this指针
        static std::string TimetoStr(time_t t)
        static void ListShow(const httplib::Request &req, httplib::Response &rsp){}
        static std::string GetETag(const BackupInfo &info){}
        static void Download(const httplib::Request &req, httplib::Response &rsp){}
    private:
        std::string _server_ip;       // IP地址
        int _server_port;             // 端口号
        std::string _download_prefix; // 下载前缀
        httplib::Server _server;      // http对象
    };
}
#endif

10. 项目总结

项目名称:云备份系统

项目功能:搭建云备份服务器与客户端,客户端程序运行在客户机上自动将指定目录下的文件备份到服务器,并且能够支持浏览器查看与下载,其中下载支持断点续传功能,并且服务器端对备份的文件进行热点管理,将长时间无访问文件进行压缩存储。

开发环境:centos7.6/vim、g++、gdb、makefile以及windows11/vs2022

技术特点:http客户端/服务器搭建,json序列化,文件压缩,热点管理,断点续传,线程池,读写锁,单例模式

项目模块:

  1. 服务端:
    1. 数据管理模块:内存中使用hash表存储提高访问效率,持久化使用文件存储管理备份数据
    2. 业务处理模块:搭建http服务器与客户端进行通信处理客户端的上传,下载,查看请求,并支持断点续传
    3. 热点管理模块:对备份的文件进行热点管理,将长时间无访问文件进行压缩存储,节省磁盘空间。
  2. 客户端
    1. 数据管理模块:内存中使用hash表存储提高访问效率,持久化使用文件存储管理备份数据
    2. 文件检索模块:基于c++17文件系统库,遍历获取指定文件夹下所有文件。
    3. 文件备份模块:搭建http客户端上传备份文件。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

云备份项目 的相关文章

  • 如何在 Unity 中从 RenderTexture 访问原始数据

    问题的简短版本 我正在尝试访问 Unity 中 RenderTexture 的内容 我一直在使用 Graphics Blit 使用自己的材质进行绘制 Graphics Blit null renderTexture material 我的材
  • 嵌入式系统中的malloc [重复]

    这个问题在这里已经有答案了 我正在使用嵌入式系统 该应用程序在 AT91SAMxxxx 和 cortex m3 lpc17xxx 上运行 我正在研究动态内存分配 因为它会极大地改变应用程序的外观 并给我更多的力量 我认为我唯一真正的路线是为
  • 使用 Microsoft Graph API 订阅 Outlook 推送通知时出现 400 错误请求错误

    我正在尝试使用 Microsoft Graph API 创建订阅以通过推送通知获取 Outlook 电子邮件 mentions 我在用本文档 https learn microsoft com en us graph api subscri
  • 为什么 POSIX 允许在只读模式下超出现有文件结尾 (fseek) 进行搜索

    为什么寻找文件结尾很有用 为什么 POSIX 让我们像示例中那样在以只读方式打开的文件中进行查找 c http en cppreference com w c io fseek http en cppreference com w c io
  • C# 中值类型和引用类型有什么区别? [复制]

    这个问题在这里已经有答案了 我知道一些差异 值类型存储在堆栈上 而引用类型存储在托管堆上 值类型变量直接包含它们的值 而引用变量仅包含对托管堆上创建的对象位置的引用 我错过了任何其他区别吗 如果是的话 它们是什么 请阅读 堆栈是一个实现细节
  • 使用 C# 在 WinRT 中获取可用磁盘空间

    DllImport kernel32 dll SetLastError true static extern bool GetDiskFreeSpaceEx string lpDirectoryName out ulong lpFreeBy
  • 如何针对 Nancy 中的 Active Directory 进行身份验证?

    这是一篇过时的文章 但是http msdn microsoft com en us library ff650308 aspx paght000026 step3 http msdn microsoft com en us library
  • tar.gz 和 tgz 是同一个东西吗? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我创建了 tgz 文件tar czvf filecommand then 我最终得到了一个 tgz 文件 我想知道它和tar gz 之间的
  • HttpClient 像浏览器一样请求

    当我通过 HttpClient 类调用网站 www livescore com 时 我总是收到错误 500 可能服务器阻止了来自 HttpClient 的请求 1 还有其他方法可以从网页获取html吗 2 如何设置标题来获取html内容 当
  • 为什么模板不能位于外部“C”块内?

    这是一个后续问题一个答案 https stackoverflow com questions 4866433 is it possible to typedef a pointer to extern c function type wit
  • Windows 窗体不会在调试模式下显示

    我最近升级到 VS 2012 我有一组在 VS 2010 中编码的 UI 测试 我试图在 VS 2012 中启动它们 我有一个 Windows 窗体 在开始时显示使用 AssemblyInitialize 属性运行测试 我使用此表单允许用户
  • 更改窗口的内容 (WPF)

    我创建了一个简单的 WPF 应用程序 它有两个 Windows 用户在第一个窗口中填写一些信息 然后单击 确定 这会将他们带到第二个窗口 这工作正常 但我试图将两个窗口合并到一个窗口中 这样只是内容发生了变化 我设法找到了这个更改窗口内容时
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • AccessViolationException 未处理

    我正在尝试使用史蒂夫 桑德森的博客文章 http blog stevensanderson com 2010 01 28 editing a variable length list aspnet mvc 2 style 为了在我的 ASP
  • 已过时 - OpenCV 的错误模式

    我正在使用 OpenCV 1 进行一些图像处理 并且对 cvSetErrMode 函数 它是 CxCore 的一部分 感到困惑 OpenCV 具有三种错误模式 叶 调用错误处理程序后 程序终止 Parent 程序没有终止 但错误处理程序被调
  • ListDictionary 类是否有通用替代方案?

    我正在查看一些示例代码 其中他们使用了ListDictionary对象来存储少量数据 大约 5 10 个对象左右 但这个数字可能会随着时间的推移而改变 我使用此类的唯一问题是 与我所做的其他所有事情不同 它不是通用的 这意味着 如果我在这里
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • 在 ASP.NET 中将事件冒泡为父级

    我已经说过 ASP NET 中的层次结构 page user control 1 user control 2 control 3 我想要做的是 当控件 3 它可以是任何类型的控件 我一般都想这样做 让用户用它做一些触发回发的事情时 它会向
  • 如何将字符串“07:35”(HH:MM) 转换为 TimeSpan

    我想知道是否有办法将 24 小时时间格式的字符串转换为 TimeSpan 现在我有一种 旧时尚风格 string stringTime 07 35 string values stringTime Split TimeSpan ts new
  • 将 viewbag 从操作控制器传递到部分视图

    我有一个带有部分视图的 mvc 视图 控制器中有一个 ActionResult 方法 它将返回 PartialView 因此 我需要将 ViewBag 数据从 ActionResult 方法传递到 Partial View 这是我的控制器

随机推荐

  • OpenType字库文件

    OpenType字库文件 一个OpenType字库文件以表的格式包含有数据 这些数据包含一个TrueType或一个PostScript outline 字库 光栅化程序使用字库里包含的表中的数据来渲染TrueType或者PostScript
  • 零基础程序员如何自学编程?用这6种方法就够了!

    PHP从入门到放弃 C语言从入门到放弃 Python从入门到放弃 在自学编程的过程中 一部分程序员遇到冰冷的英语字母 枯燥的编程教程 果断选择了放弃 但其实自学编程不是那么难 只要是理工科生 逻辑思维还行的小伙伴 编程入门完全可以 下面给程
  • 用Podman来代替Docker Desktop

    文章目录 用Podman来代替Docker Desktop 更新 前言 在Mac上安装Podman 在Windows上安装Podman 测试Podman 用podman compose运行Docker Compose 用Podman直接操作
  • Android实现省市区三级联动效果

    PickerView控件的作者在3 0版本中对PickerView源码进行了重构 重构后的PickerView添加了很多可自定义的属性 比如可以自定义文字颜色 大小等 使用也更加方便了 只是改动较大 使用方法也与2 0版本有不少差别 由于2
  • datacom-IPV6

    一 概念 1 IPV6与IPV4相比的优点 1 地址容量大 2 层次结构设计更合理 方便路由汇聚 3 即插即用 SLAAC 4 报头经过了简化 提高了转发效率 5 更安全 IPSEC 6 更好的移动性 7 QOS增强 2 IPV6和IPV4
  • 03Linux下静态库和动态库(共享库)的制作与使用

    Linux下静态库和动态库 共享库 的制作与使用 Linux操作系统支持的函数库分为 静态库 libxxx a 在编译时就将库编译进可执行程序中 lib 前缀 固定 a 后缀 固定 优点 程序的运行环境中不需要外部的函数库 缺点 可执行程序
  • Oracle 报表常用sql

    Oracle 报表常用sql 数据库建模式 用户 表空间 表 数据语句在最末尾 一 数据类型转化 函数 translate 字段 USING NCHAR CS 样例 SELECT translate COLUMN1 USING NCHAR
  • Centos8安装MySQL(亲测有效)

    1 下载压缩包 https cdn mysql com Downloads MySQL 5 7 mysql 5 7 29 1 el7 x86 64 rpm bundle tar 2 上传到服务器 命令 rz 3 解压 tar xvf mys
  • dll修复工具安装教程

    电脑显示dll软件报错 相信有很多小伙伴遇到过这种情况 一起来看看呗 亲测有用 可以一键检测和修复Windows系统中存在的DLL问题 SYS问题以及注册表问题 并拥有完善的DLL库供用户搜索下载 此外dll修复工具还支持注册表优化 启动项
  • 【论文&模型讲解】多模态对话 Multimodal Dialogue Response Generation

    文章目录 前言 0 摘要 1 Introduction 2 相关工作 2 1 文本对话回复生成 2 2 Text to Image 生成 3 Problem Formailzation 4 Approach 4 1 多模态 Tokeniza
  • C#中this关键字的使用

    01 消除字段歧义 public class Writer private int age private String name public Writer int age String name this age age this na
  • 灰灰-324-2019华科软院学硕上机(二)-魔方阵:vector、resize()、setw()

    魔方阵 古代又称 纵横图 是指组成元素为自然数1 2 n的平方的n n的方阵 其中每个元素值都不相等 且每行 每列以及主 副对角线上各n个元素之和都相等 阶数大于等于3 如3 3的魔方阵 8 1 6 3 5 7 4 9 2 奇数魔方阵的排列
  • ARDUINO使用GPRS发送GPS数据到OneNet测试

    功能 测试把固定的GPS数据发送到OneNet平台 调试途中碰到的问题 ARDUINO不支持sprintf的double打印 只能转换为char字符串然后再 s打印 include
  • 永磁同步电机(PMSM)磁场定向控制(FOC)电流环PI调节器参数整定

    文章目录 前言 一 调节器的工程设计方法 二 电流环PI调节器的参数整定 2 1 电流环的结构框图 2 2 典型I型系统 2 3 电流环PI参数整定计算公式 三 电流环PI调节器设计实例 3 1 永磁同步电机磁场定向的电流闭环控制 3 2
  • 关于qt 读写结构体

    目录 前言 一 注意事项 1 1 需求 1 2 读文件报错 1 2 1 文件写入 1 2 2 文件读取 1 2 3 文件写入 1 2 4 文件读取 二 解决方案 2 1 正确实例代码 2 1 1 头文件 2 1 2 源文件 2 1 3 文件
  • 响应式布局的常用解决方案对比(媒体查询、百分比、rem和vw/vh)

    简要介绍 前端开发中 静态网页通常需要适应不同分辨率的设备 常用的自适应解决方案包括媒体查询 百分比 rem和vw vh等 本文从px单位出发 分析了px在移动端布局中的不足 接着介绍了几种不同的自适应解决方案 本文原文在我的github主
  • 【粉丝问答9】一起入职的同事能力不如我,只因学历比我高,工资是我的两倍

    一起入职的同事能力不如我 只因学历比我高 工资是我的两倍 我想这是很多初入职场的同学经常会遇到的一个问题 本篇只针对研发人员 一口君有个朋友C君刚毕业的第一家 也遇到过类似的问题 C君是本科进入做路由器的协议开发工作 辛辛苦苦开发的软件模块
  • Linux Sed命令详解

    概述 sed是stream editor的简称 也就是流编辑器 它一次处理一行内容 处理时 把当前处理的行存储在临时缓冲区中 称为 pattern space 接着用sed命令处理缓冲区中的内容 处理完成后 把缓冲区的内容送往屏幕 接着处理
  • KITTI数据集解析

    KITTI 数据集解析 本文主要是对于3D目标检测中 KITTI数据集的分析 数据下载 KITTI 官网链接 下载的主要有 left color images velodyne point clouds camera calibration
  • 云备份项目

    云备份项目 1 云备份认识 自动将本地计算机上指定文件夹中需要备份的文件上传备份到服务器中 并且能够随时通过浏览器进行查看并且下载 其中下载过程支持断点续传功能 而服务器也会对上传文件进行热点管理 将非热点文件进行压缩存储 节省磁盘空间 2