云備份項目--工具類編寫

4. 文件工具類的設計

4.1 整體的類

該類實現對文件進行操作

FileUtil.hpp如下

/*
該類實現對文件進行操作
*/
#pragma once
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#include <experimental/filesystem>      // c++17 的文件系統庫
#include "bundle.h"namespace cloud
{
namespace fs = std::experimental::filesystem;class FileUtil
{
private:std::string _fileName;struct stat _st;        // 用于獲取文件的各種屬性
public:// 輸入一個路徑FileUtil(std::string fileName) : _fileName(fileName) {if(stat(_fileName.c_str(), &_st) < 0) {std::cerr << "獲取文件屬性失敗!\nstat(_fileName.c_str(), &_st) error! why: " << strerror(errno) << '\n';// exit(1);}}// 獲取文件大小(單位是字節)int64_t getFileSize(){return _st.st_size;      // 返回字節數,有符號的長整型}// 獲取文件最后一次修改時間time_t getLastMTime(){return _st.st_mtime;}// 獲取文件最后一次訪問時間time_t getLastATime(){return _st.st_atime;}// 獲得一個路徑最后文件的名稱,例如/abc/a.txt -> a.txtstd::string getFileName(){ssize_t pos = _fileName.find_last_of('/');if(pos == std::string::npos) {// 沒有/,證明這就是一個文件,沒有文件夾return _fileName;}// 有/,要截取字符串return _fileName.substr(pos+1);}// 從pos位置獲取len長度的數據(單位是字節),寫到s中bool getContentFromPos(std::string *s, size_t pos, size_t len){int64_t fileSz = getFileSize();if(pos + len > fileSz) {// 申請的長度大于文件長度std::cerr << "Bad size!\nbool getContentFromPos(std::string *s, size_t pos, size_t len)\n";return false;}// 用來讀取文件std::ifstream ifile(_fileName, std::ios::binary);// 是否打開成功if(ifile.is_open() == false) {std::cerr << "Open file error!\nbool getContentFromPos(std::string *s, size_t pos, size_t len)\n";ifile.close();return false;}// 讀取文件內容ifile.seekg(pos, std::ios::beg);s->resize(len);     ifile.read((char*)(s->c_str()), len);// 檢測這個流的狀態是否okif(ifile.good() == false) {std::cerr << "read file error!\nbool getContentFromPos(std::string *s, size_t pos, size_t len)\n";ifile.close();return false;}return true;}// 獲取文件的所有內容,寫到s中bool getFullContent(std::string *s) {// 調用getContentFromPos()return getContentFromPos(s, 0, getFileSize());}// 將字符串s的內容寫入到文件中bool setContent(const std::string& s){// 用來像文件寫入std::ofstream ofile(_fileName, std::ios::binary);// 是否打開成功if(ofile.is_open() == false) {std::cerr << "Open file error!\nbool setContent(const std::string& s)\n";ofile.close();return false;}ofile.write((char*)s.c_str(), s.size());// 檢測這個流的狀態是否okif(ofile.good() == false) {std::cerr << "write file error!\nbool setContent(const std::string& s)\n";ofile.close();return false;}return true;}// 壓縮,packName是壓縮包的名字bool compresss(const std::string& packName){// 先讀取文件內容std::string content;if(getFullContent(&content) == false) {std::cerr << "bool compresss(const std::string& packName) get content error!\n";return false;}// 壓縮文件內容,這里使用LZIP壓縮格式std::string packContent = bundle::pack(bundle::LZIP, content);cloud::FileUtil newFile(packName);// 將內容寫到新的文件if(newFile.setContent(packContent) == false) {std::cerr << "bool compresss(const std::string& packName) set content error!\n";return false;}return true;}// 解壓,fileName是解壓后新文件的名字bool unCompress(const std::string& fileName){// 先讀取文件內容std::string content;if(getFullContent(&content) == false) {std::cerr << "bool unCompress(const std::string& packName) get content error!\n";return false;}// 解壓文件內容std::string unpackContent = bundle::unpack(content);cloud::FileUtil newFile(fileName);// 將內容寫到新的文件if(newFile.setContent(unpackContent) == false) {std::cerr << "bool unCompresss(const std::string& packName) set content error!\n";return false;}return true;}// 判斷文件是否存在,存在返回truebool exits(){return fs::exists(_fileName);}// 創建目錄,創建成功返回truebool createDir(){// 如果該文件存在了,就直接返回trueif(exits())    return true;return fs::create_directories(_fileName);}// 掃描文件夾下的文件,放到數組中bool scanDir(std::vector<std::string> *array){   for (const fs::directory_entry& entry : fs::directory_iterator(_fileName)) {if(fs::is_directory(entry) == true) {// 如果是目錄的話,跳過,該函數只掃描一般文件continue;}array->push_back(entry.path().relative_path().string());}   }
};}

makefile如下

cloud : Cloud.cpp bundle.cpp FileUtil.hppg++ $^ -o $@ -lpthread -lstdc++fs.PHONY : clean
clean:rm -f cloud

4.2 測試

4.2.1 測試獲取文件屬性功能

Cloud.cpp

#include "FileUtil.hpp"// 測試獲取文件屬性功能
void testFileUtil(const std::string& s)
{cloud::FileUtil f(s);printf("文件大小: %ld\n", f.getFileSize());printf("文件最后一次修改時間: %ld\n", f.getLastMTime());printf("文件最后一次訪問時間: %ld\n", f.getLastATime());printf("獲得一個路徑最后文件的名稱: %s\n", f.getFileName().c_str());
}int main(int argc, char* argv[])
{if(argc != 2) {std::cerr << "usage error!\n"; return -1;}testFileUtil(argv[1]);return 0;
}

結果如下

lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ ./cloud test.txt 
文件大小: 28
文件最后一次修改時間: 1734504144
文件最后一次訪問時間: 1734504157
獲得一個路徑最后文件的名稱: test.txt
---------------------------------------------------------------------------
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ ./cloud ../../lib/bundle/README.md 
文件大小: 16571
文件最后一次修改時間: 1734185453
文件最后一次訪問時間: 1734185453
獲得一個路徑最后文件的名稱: README.md
---------------------------------------------------------------------------
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ ./cloud aaaa.txt
獲取文件屬性失敗!
stat(_fileName.c_str(), &_st) error! why: No such file or directory

4.2.2 測試文件讀寫功能

void testFileUtil2(const std::string& fileName)
{cloud::FileUtil f(fileName);std::string s;f.getFullContent(&s);// std::cout << s;cloud::FileUtil of("writeTest.txt");        // 打開一個名為writeTest.txt的文件,沒有則創建of.setContent(s);
}int main(int argc, char* argv[])
{if(argc != 2) {std::cerr << "usage error!\n"; return -1;}testFileUtil2(argv[1]);return 0;
}
目前有個文件test.txt
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ cat test.txt 
abcdefghigklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
---------------------------------------------------------------------------
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ ./cloud test.txt 
獲取文件屬性失敗!
stat(_fileName.c_str(), &_st) error! why: No such file or directory
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ ll
total 52
drwxrwxr-x  2 lyf lyf  4096 Dec 18 16:20 ./
drwxrwxr-x 23 lyf lyf  4096 Dec 18 11:31 ../
-rwxrwxr-x  1 lyf lyf 24144 Dec 18 16:20 cloud*
-rw-rw-r--  1 lyf lyf   969 Dec 18 16:16 Cloud.cpp
-rw-rw-r--  1 lyf lyf  3516 Dec 18 16:20 FileUtil.hpp
-rw-rw-r--  1 lyf lyf    67 Dec 18 16:14 makefile
-rw-rw-r--  1 lyf lyf    53 Dec 18 16:14 test.txt
-rw-rw-r--  1 lyf lyf    53 Dec 18 16:20 writeTest.txt
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ cat writeTest.txt 
abcdefghigklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ

4.2.3 測試壓縮和解壓縮功能

lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ ./cloud bundle.cpp 
獲取文件屬性失敗!
stat(_fileName.c_str(), &_st) error! why: No such file or directory
獲取文件屬性失敗!
stat(_fileName.c_str(), &_st) error! why: No such file or directory
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ ls -lh
total 15M
-rw-rw-r-- 1 lyf lyf 5.4M Dec 18 19:14 bundle.cpp
-rw-rw-r-- 1 lyf lyf 668K Dec 18 19:34 bundle.cpp.lz
-rw-rw-r-- 1 lyf lyf  29K Dec 18 19:14 bundle.h
-rwxrwxr-x 1 lyf lyf 3.3M Dec 18 19:33 cloud
-rw-rw-r-- 1 lyf lyf 1.3K Dec 18 19:33 Cloud.cpp
-rw-rw-r-- 1 lyf lyf 5.0K Dec 18 19:24 FileUtil.hpp
-rw-rw-r-- 1 lyf lyf  101 Dec 18 19:28 makefile
-rw-rw-r-- 1 lyf lyf 5.4M Dec 18 19:34 newname.cpp
-rw-rw-r-- 1 lyf lyf   23 Dec 18 19:32 test.txt
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ md5sum bundle.cpp
4cb64c7a8354c82402dd6fe080703650  bundle.cpp
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ md5sum newname.cpp 
4cb64c7a8354c82402dd6fe080703650  newname.cpp

4.2.4 測試目錄功能

// 測試目錄操作
void testFileUtil4(const std::string& fileName)
{cloud::FileUtil f(fileName);f.createDir();      // 創建一個文件夾std::vector<std::string> array;f.scanDir(&array);// 打印目錄下的文件內容for(const auto& e : array) {std::cout << e << '\n';}
}
# 獲取文件夾下的所有文件
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ ls
bundle.cpp  bundle.h  cloud  Cloud.cpp  FileUtil.hpp  makefile  test.txt
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ ./cloud test
獲取文件屬性失敗!
stat(_fileName.c_str(), &_st) error! why: No such file or directory
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ ls
bundle.cpp  bundle.h  cloud  Cloud.cpp  FileUtil.hpp  makefile  test  test.txt
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ cd test/
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份/test$ ll
total 8
drwxrwxr-x 2 lyf lyf 4096 Dec 18 21:53 ./
drwxrwxr-x 3 lyf lyf 4096 Dec 18 21:53 ../
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份/test$ touch a.txt
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份/test$ touch b.cc
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份/test$ touch c.java
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份/test$ touch d.python
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份/test$ cd ../
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ ./cloud ./test
./test/c.java
./test/d.python
./test/b.cc
./test/a.txt

5. Json工具類的設計

5.1 整體的類

#pragma once
#include <iostream>
#include <jsoncpp/json/json.h>
#include <string>
#include <sstream>
#include <memory>namespace cloud
{
class JsonUtil
{
public:// 將root的序列化結果保存在str中static bool serialize(const Json::Value& root, std::string* str){Json::StreamWriterBuilder swb;std::unique_ptr<Json::StreamWriter> ps(swb.newStreamWriter());std::stringstream ss;if (ps->write(root, &ss) != 0) {std:: cerr << "write error!\nstatic bool serialize(const Json::Value& root, std::string* str)\n";return false;} *str = ss.str();return true;}// 將str的序列化結果保存在root中static bool unserialize(const std::string& str, Json::Value* root){Json::CharReaderBuilder crb;std::unique_ptr<Json::CharReader> ps(crb.newCharReader());std::string errs;if (ps->parse(str.c_str(), str.c_str() + str.size(), root, &errs) == false) {std::cerr << "parse error!, why: " << str  << "\nstatic bool unserialize(const std::string& str, Json::Value* root)\n";return false;}return true;}
};
}

5.2 測試序列化工具類

// 測試JsonUtil
void testJsonUtil()
{/* 序列化 */std::string name = "zhangsan";int age = 20;int scores[] = {80, 90, 100};// 給數據對象類添加數據Json::Value value;value["name"] = name;value["age"] = age;value["score"].append(scores[0]);value["score"].append(scores[1]);value["score"].append(scores[2]);std::string str;cloud::JsonUtil::serialize(value, &str);printf("序列化結果:\n %s\n%s\n", str.c_str(), "========================================");Json::Value oValue;/* 反序列化, 將s反序列化*/cloud::JsonUtil::unserialize(str, &oValue);printf("反序列化結果: \nname: %s\nage: %d\n", (oValue["name"].asString()).c_str(), oValue["age"].asInt());for(int i = 0; i < 3; ++i) {printf("成績%d: %d\n", i, oValue["score"][i].asInt());}
}
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ ./cloud 
序列化結果:{"age" : 20,"name" : "zhangsan","score" : [80,90,100]
}
========================================
反序列化結果: 
name: zhangsan
age: 20
成績0: 80
成績1: 90
成績2: 100

6. 服務端所用到的配置信息

6.1 json格式的配置信息

  • 服務器訪問 IP 地址

  • 服務器訪問端?

  • 熱點判斷時間(多長時間沒有被訪問的文件屬于非熱點文件)

  • URL路徑前綴(如http://www.example.com/path/to/file的路徑前綴是/path/

  • 壓縮包后綴名稱 (在文件原名后面加上該后綴)

  • 上傳?件存放路徑(上傳后的文件儲存在服務器的哪個文件夾下)

  • 壓縮?件存放路徑(壓縮文件儲存在服務器的哪個文件夾下)

  • 服務端備份信息存放文件名 (可以通過數據庫存放)

使用json格式存放,下面是一個實例。cloud.conf

TODO: 構造函數出錯返回?
將bundle變成一個庫

{"serverIp" : "124.70.203.1","serverPort" : 9000,"hotTime" : 30,"pathPre" : "/listShow/","rarSuf" : ".lz","ulPath" : "./files","rarPath" : "./rars","backups" : "./backups.data"
}

6.2 加載配置信息類

6.2.1 完整的類

使用單例模式。config.hpp

/* 用于加載配置文件 */
#include "FileUtil.hpp"
#include "JsonUtil.hpp"
#include <mutex>
#define CONF_PATH "./cloud.conf"namespace cloud
{
class Config
{
private:static Config* _instance;static std::mutex _mtx;Config(const Config& c) = delete;Config& operator=(const Config& c) = delete;Config() {if(loadFiles() == false)    delInstance();}// 從配置文件中加載數據,放到各個屬性中bool loadFiles(){   // 打開文件cloud::FileUtil fu(CONF_PATH);std::string content;if(fu.getFullContent(&content) == false) {std::cerr << "getFullContent error!\nbool loadFiles()\n";return false;}// json轉換Json::Value root;if(cloud::JsonUtil::unserialize(content, &root) == false) {std::cerr << "unserialize error!\nbool loadFiles()\n";return false;}// 初始化_serverIp = root["serverIp"].asString();_serverPort = root["serverPort"].asInt();_hotTime = root["hotTime"].asInt64();_pathPre = root["pathPre"].asString();_rarSuf = root["rarSuf"].asString();_ulPath = root["ulPath"].asString();_rarPath = root["rarPath"].asString();_backups = root["backups"].asString();return true;}
private:std::string _serverIp;  // 服務器訪問 IP 地址  int _serverPort;        // 服務器訪問端? std::time_t _hotTime;   // 熱點判斷時間std::string _pathPre;   // URL路徑前綴std::string _rarSuf;    // 壓縮包后綴名稱std::string _ulPath;    // 上傳文件存放的路徑std::string _rarPath;   // 壓縮文件存放的路徑std::string _backups;   // 備份文件
public:// 獲取實例static Config* getInstance(){if(_instance == nullptr) {      // _instance為null時,才有加鎖解鎖的必要。外面多加一層判斷可以防止每次getInstance()時都要申請鎖std::unique_lock<std::mutex> lck(_mtx);if(_instance == nullptr) {_instance = new Config();}}return _instance;}// 刪除實例static void delInstance(){if(_instance != nullptr) {std::cout << "log: static void delInstance()\n";delete _instance;_instance = nullptr;}}std::string getServerIp() { return _serverIp; }int getServerPort() { return _serverPort; }std::time_t getHotTime() { return _hotTime; }std::string getPathPre() { return _pathPre; }std::string getRarSuf() { return _rarSuf; }std::string getUlPath() { return _ulPath; }std::string getRarPath() { return _rarPath; }std::string getBackups() { return _backups; } 
};
Config* Config::_instance = nullptr;
std::mutex Config::_mtx;
}

6.2.2 測試

// 測試Config.hpp
void testConfig()
{   cloud::Config* cof = cloud::Config::getInstance();std::cout << cof->getServerIp() << '\n';std::cout << cof->getServerPort() << '\n';std::cout << cof->getHotTime() << '\n';std::cout << cof->getPathPre() << '\n';std::cout << cof->getRarSuf() << '\n';std::cout << cof->getUlPath() << '\n';std::cout << cof->getRarPath() << '\n';std::cout << cof->getBackups() << '\n';
}
lyf@hcss-ecs-3db9:~/pro/pro24_12_18云備份$ ./cloud 
124.70.203.1
9000
30
/listShow/
.lz
./files
./rars
./backups.data

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/63750.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/63750.shtml
英文地址,請注明出處:http://en.pswp.cn/web/63750.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

51c大模型~合集94

我自己的原文哦~ https://blog.51cto.com/whaosoft/12897659 #D(R,O) Grasp 重塑跨智能體靈巧手抓取&#xff0c;NUS邵林團隊提出全新交互式表征&#xff0c;斬獲CoRL Workshop最佳機器人論文獎 本文的作者均來自新加坡國立大學 LinS Lab。本文的共同第一作者為上海交通大…

【大學英語】英語范文十八篇,書信,議論文,材料分析

關注作者了解更多 我的其他CSDN專欄 過程控制系統 工程測試技術 虛擬儀器技術 可編程控制器 工業現場總線 數字圖像處理 智能控制 傳感器技術 嵌入式系統 復變函數與積分變換 單片機原理 線性代數 大學物理 熱工與工程流體力學 數字信號處理 光電融合集成電路…

一起學Git【第一節:Git的安裝】

Git是什么&#xff1f; Git是什么&#xff1f;相信大家點擊進來已經有了初步的認識&#xff0c;這里就簡單的進行介紹。 Git是一個開源的分布式版本控制系統&#xff0c;由Linus Torvalds創建&#xff0c;用于有效、高速地處理從小到大的項目版本管理。Git是目前世界上最流行…

消息隊列 Kafka 架構組件及其特性

Kafka 人們通常有時會將 Kafka 中的 Topic 比作隊列&#xff1b; 在 Kafka 中&#xff0c;數據是以主題&#xff08;Topic&#xff09;的形式組織的&#xff0c;每個 Topic 可以被分為多個分區&#xff08;Partition&#xff09;。每個 Partition 是一個有序的、不可變的消息…

《Mycat核心技術》第06章:Mycat問題處理總結

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章匯總&#xff1a;https://binghe.gitcode.host/md/all/all.html 星球項目地址&#xff1a;https://binghe.gitcode.host/md/zsxq/introduce.html 沉淀&#xff0c…

【day11】面向對象編程進階(繼承)

概述 本文深入探討面向對象編程的核心概念&#xff0c;包括繼承、方法重寫、this和super關鍵字的使用&#xff0c;以及抽象類和方法的定義與實現。通過本文的學習&#xff0c;你將能夠&#xff1a; 理解繼承的優勢。掌握繼承的使用方法。了解繼承后成員變量和成員方法的訪問特…

隨手記:小程序兼容后臺的wangEditor富文本配置鏈接

場景&#xff1a; 在后臺配置wangEditor富文本&#xff0c;可以文字配置鏈接&#xff0c;圖片配置鏈接&#xff0c;產生的json格式為&#xff1a; 例子&#xff1a; <h1><a href"https://uniapp.dcloud.net.cn/" target"_blank"><span sty…

6.8 Newman自動化運行Postman測試集

歡迎大家訂閱【軟件測試】 專欄&#xff0c;開啟你的軟件測試學習之旅&#xff01; 文章目錄 1 安裝Node.js2 安裝Newman3 使用Newman運行Postman測試集3.1 導出Postman集合3.2 使用Newman運行集合3.3 Newman常用參數3.4 Newman報告格式 4 使用定時任務自動化執行腳本4.1 編寫B…

工具環境 | 工具準備

搭建一套驗證環境需要的工具如下&#xff1a; 虛擬機&#xff1a;推薦virtualbox ubuntu VM好用&#xff0c;但是免費的好像木有了&#xff0c;ubuntu界面版更加容易上手。 網上找安裝教程即可&#xff0c;注意實現文件共享、復制粘貼等功能。 EDA&#xff1a;VCS Veridi 工…

計算機網絡之王道考研讀書筆記-2

第 2 章 物理層 2.1 通信基礎 2.1.1 基本概念 1.數據、信號與碼元 通信的目的是傳輸信息。數據是指傳送信息的實體。信號則是數據的電氣或電磁表現&#xff0c;是數據在傳輸過程中的存在形式。碼元是數字通信中數字信號的計量單位&#xff0c;這個時長內的信號稱為 k 進制碼…

ROS2學習配套C++知識

第3章 訂閱和發布——話題通信探索 3.3.1 發布速度控制海龜畫圓 std::bind cstd::bind綁定成員函數時&#xff0c;需要加上作用域以及取址符號 因為不會將成員函數隱式的轉換成指針&#xff0c;因此需要加&符號&#xff1b; 后面的第一個參數必須跟具體對象&#xff0c;c…

法規標準-C-NCAP評測標準解析(2024版)

文章目錄 什么是C-NCAP&#xff1f;C-NCAP 評測標準C-NCAP評測維度三大維度的評測場景及對應分數評星標準 自動駕駛相關評測場景評測方法及評測標準AEB VRU——評測內容(測什么&#xff1f;)AEB VRU——評測方法(怎么測&#xff1f;)車輛直行與前方縱向行走的行人測試場景&…

第十七屆山東省職業院校技能大賽 中職組“網絡安全”賽項任務書正式賽題

第十七屆山東省職業院校技能大賽 中職組“網絡安全”賽項任務書-A 目錄 一、競賽階段 二、競賽任務書內容 &#xff08;一&#xff09;拓撲圖 &#xff08;二&#xff09;模塊A 基礎設施設置與安全加固(200分) &#xff08;三&#xff09;B模塊安全事件響應/網絡安全數據取證/…

mlr3機器學習AUC的置信區間提取

如果你在mlr3拿到機器學習的預測數據 ROC 過程原理探索 假設數據 df <- data.frame(Airis$Sepal.Length, groupsample(x c(0,1),size 150,replace T)) 分組為 0,1 # 變量A為連續性變量 library(pROC) roc_obj <- roc(df g r o u p , d f group, df group,dfA, le…

Halcon例程代碼解讀:安全環檢測(附源碼|圖像下載鏈接)

安全環檢測核心思路與代碼詳解 項目目標 本項目的目標是檢測圖像中的安全環位置和方向。通過形狀匹配技術&#xff0c;從一張模型圖像中提取安全環的特征&#xff0c;并在后續圖像中識別多個實例&#xff0c;完成檢測和方向標定。 實現思路 安全環檢測分為以下核心步驟&…

Java——多線程進階知識

目錄 一、常見的鎖策略 樂觀鎖VS悲觀鎖 讀寫鎖 重量級鎖VS輕量級鎖 總結&#xff1a; 自旋鎖&#xff08;Spin Lock&#xff09; 公平鎖VS非公平鎖 可重入鎖VS不可重入鎖 二、CAS 何為CAS CAS有哪些應用 1&#xff09;實現原子類 2&#xff09;實現自旋鎖 CAS的ABA…

ubuntu18.04升級到ubuntu20.04

為了使用qt6&#xff0c;在ubuntu18.04上各種折騰失敗&#xff0c;無奈只能升級到ubuntu20.04, 按照網上的教程沒成功。自己摸索了 lsb_release -a df -h sudo apt update sudo apt upgrade -y sudo apt dist-upgrade -y sudo apt autoremove -y sudo apt clean sudo apt inst…

【Blender】【源碼詳解】BLI_mesh_boolean 實現詳解

1. 背景&#xff1a; 最近因為項目需要&#xff0c;需要閱讀 Blender 中關于 mesh boolean 的源碼&#xff1b;因此&#xff0c;對 blender 中的 mesh boolean 源碼進行解讀&#xff1b; Github 上源碼下載很慢&#xff0c;一般使用 Gitee: gitee Blender 源碼 2. Mesh Boole…

qcow2鏡像大小壓縮

本文擬對qcow2進行壓縮進行簡單介紹 背景 qcow2鏡像在使用一段時間后&#xff0c;總是會不斷膨脹變大&#xff0c;所以在導出分享時一般都需要進行壓縮以縮減占用空間。 清除空洞 qcow2方式也有稀疏的問題&#xff0c;在磁盤級別上看&#xff0c;鏡像會有大量連續的相同空洞…

達夢 本地編碼:PG_GBK, 導入文件編碼:PG_UTF8錯誤

問題 達夢 本地編碼&#xff1a;PG_GBK, 導入文件編碼&#xff1a;PG_UTF8錯誤 解決 右鍵管理服務器 查看配置 新建一個數據庫實例&#xff0c;配置跟之前的保持一致 新建一個用戶&#xff0c;跟以前的用戶名一樣 在用戶上&#xff0c;右鍵導入&#xff0c;選擇dmp的位置 導…