C++로 파일 변경 내역을 유지하는 방법
31141 단어 reductstoragebeginnerstutorialcpp
축소 스토리지 실행
Linux 사용자인 경우 저장소 엔진을 실행하는 가장 쉬운 방법은 Docker입니다. 다음은
docker-compose.yml
파일의 예입니다.services:
reduct-storage:
image: reductstorage/engine:v1.0.1
volumes:
- ./data:/data
environment:
RS_LOG_LEVEL: DEBUG
ports:
- 8383:8383
다운로드binaries하고 실행할 수도 있습니다.
RS_DATA_PATH=./data reduct-storage
모든 것이 정상이면 http://127.0.0.1:8383에 웹 콘솔이 표시되어야 합니다.
C++용 Reduction Storage SDK 설치
현재 라이브러리를 수동으로만 빌드하고 설치할 수 있습니다. 팔로우this instruction .
C++의 파일 감시자
SDK는 cmake find 스크립트를 제공하므로 CMake 프로젝트에 쉽게 통합할 수 있습니다. 다음은 CMakeLists.txt의 예입니다.
cmake_minimum_required(VERSION 3.23)
project(file_watcher_example)
set(CMAKE_CXX_STANDARD 20)
find_package(ReductCpp 1.0.1)
find_package(ZLIB)
find_package(OpenSSL)
add_executable(file_watcher main.cc)
target_link_libraries(file_watcher
${REDUCT_CPP_LIBRARIES} ${ZLIB_LIBRARIES}
OpenSSL::SSL OpenSSL::Crypto)
이제 C++ 코드를 작성할 준비가 되었습니다. 당사
main.cc
파일:#include <reduct/client.h>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <map>
#include <regex>
#include <thread>
constexpr std::string_view kReductStorageUrl = "http://127.0.0.1:8383";
constexpr std::string_view kWatchedPath = "./";
namespace fs = std::filesystem;
int main() {
using ReductClient = reduct::IClient;
using ReductBucket = reduct::IBucket;
auto client = ReductClient::Build(kReductStorageUrl);
auto [bucket, err] = client->GetOrCreateBucket(
"watched_files", ReductBucket::Settings{
.quota_type = ReductBucket::QuotaType::kFifo,
.quota_size = 100'000'000, // 100Mb
});
if (err) {
std::cerr << "Failed to create bucket" << err << std::endl;
return -1;
}
std::cout << "Create bucket" << std::endl;
std::map<std::string, fs::file_time_type> file_timestamp_map;
for (;;) {
for (auto& file : fs::directory_iterator(kWatchedPath)) {
bool is_changed = false;
// check only files
if (!fs::is_regular_file(file)) {
continue;
}
const auto filename = file.path().filename().string();
auto ts = fs::last_write_time(file);
if (file_timestamp_map.contains(filename)) {
auto& last_ts = file_timestamp_map[filename];
if (ts != last_ts) {
is_changed = true;
}
last_ts = ts;
} else {
file_timestamp_map[filename] = ts;
is_changed = true;
}
if (!is_changed) {
continue;
}
std::string alias = filename;
std::regex_replace(
alias.begin(), filename.begin(), filename.end(), std::regex("\\."),
"_"); // we use filename as an entyr name. It can't contain dots.
std::cout << "`" << filename << "` is changed. Storing as `" << alias
<< "` ";
std::ifstream changed_file(file.path());
if (!changed_file) {
std::cerr << "Failed open file";
return -1;
}
auto file_size = fs::file_size(file);
auto write_err = bucket->Write(
alias, std::chrono::file_clock::to_sys(ts),
[file_size, &changed_file](ReductBucket::WritableRecord* rec) {
rec->Write(file_size, [&](size_t offest, size_t size) {
std::string buffer;
buffer.resize(size);
changed_file.read(buffer.data(), size);
std::cout << "." << std::flush;
return std::pair{offest + size <= file_size, buffer};
});
});
if (write_err) {
std::cout << " Err:" << write_err << std::endl;
} else {
std::cout << " OK (" << file_size / 1024 << " kB)" << std::endl;
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
return 0;
}
좋아요, 꽤 많은 줄이 있지만 걱정하지 마세요. 이것은 간단한 프로그램입니다. 코드를 자세히 살펴보겠습니다.
버킷 생성
데이터베이스에 쓰기를 시작하려면 버킷을 생성해야 합니다.
auto client = ReductClient::Build(kReductStorageUrl);
auto [bucket, err] = client->GetOrCreateBucket(
"watched_files", ReductBucket::Settings{
.quota_type = ReductBucket::QuotaType::kFifo,
.quota_size = 100'000'000, // 100Mb
});
if (err) {
std::cerr << "Failed to create bucket" << err << std::endl;
return -1;
}
여기에서
kReductStorageUrl
URL이 있는 스토리지 엔진을 사용해야 하는 클라이언트를 빌드합니다. 그런 다음 이름이 watched_files
인 버킷을 생성하거나 기존 버킷을 가져옵니다. 이 할당량에 도달하면 스토리지 엔진이 오래된 데이터를 제거하기 시작하도록 100Mb로 크기를 제한하는 몇 가지 설정도 제공합니다.SDK는 예외를 발생시키지 않습니다. 각 메서드는
reduct::Error
또는 reduct::Result<T>
를 반환하므로 코드에서 결과를 쉽게 확인하고 오류 메시지를 인쇄할 수 있습니다.파일 보기
간단한 방법으로 파일 감시자를 구현합니다.
std::map<std::string, fs::file_time_type> file_timestamp_map;
for (;;) {
for (auto& file : fs::directory_iterator(kWatchedPath)) {
bool is_changed = false;
// check only files
if (!fs::is_regular_file(file)) {
continue;
}
const auto filename = file.path().filename().string();
auto ts = fs::last_write_time(file);
if (file_timestamp_map.contains(filename)) {
auto& last_ts = file_timestamp_map[filename];
if (ts != last_ts) {
is_changed = true;
}
last_ts = ts;
} else {
file_timestamp_map[filename] = ts;
is_changed = true;
}
if (!is_changed) {
continue;
}
// Storing a changed file...
std::this_thread::sleep_for(
std::chrono::milliseconds(100));
}
주어진 디렉토리
fs::directory_iterator(kWatchedPath)
를 통해 이동하고 각 파일의 마지막 수정 시간을 file_timestamp_map
맵에 보관합니다. 새 파일(맵에 없음)이거나 변경된 경우(타임스탬프가 다름) 변경된 파일 저장을 시작하도록 is_changed
플래그를 설정합니다.CPU 과부하를 피하기 위해 각 주기가 끝날 때 잠시 잠을 자는 것을 잊지 마십시오.
파일 저장
파일의 히스토리는 Reduct Storage에서 an entry으로 표현됩니다. 항목 이름에 "."을 사용할 수 없기 때문입니다. 파일 이름에서 다음과 같이 바꿔야 합니다.
std::string alias = filename;
std::regex_replace(
alias.begin(), filename.begin(), filename.end(), std::regex("\\."),
"_"); // we use filename as an entyr name. It can't contain dots.
std::cout << "`" << filename << "` is changed. Storing as `" << alias
<< "` ";
그런 다음 읽기 위해 변경된 파일을 엽니다.
std::ifstream changed_file(file.path());
if (!changed_file) {
std::cerr << "Failed open file";
return -1;
}
그리고 스토리지 엔진에 청크 단위로 작성합니다.
auto file_size = fs::file_size(file);
auto write_err = bucket->Write(
alias, std::chrono::file_clock::to_sys(ts),
[file_size, &changed_file](ReductBucket::WritableRecord* rec) {
rec->Write(file_size, [&](size_t offest, size_t size) {
std::string buffer;
buffer.resize(size);
changed_file.read(buffer.data(), size);
std::cout << "." << std::flush;
return std::pair{offest + size <= file_size, buffer};
});
});
보시다시피 매우 장황하지만 작은 덩어리로 파일을 보내고 메모리에 대한 걱정 없이 테라바이트를 보낼 수 있습니다! 거대한 파일을 여러분의 감시 디렉토리에 넣으면 Reduct Storage가 얼마나 빠른지 알 수 있습니다.
데이터 가져오기
Bucket::Query 메서드를 사용하여 데이터를 가져올 수 있습니다. 또한 Python 또는 JavaScript 클라이언트 SDK를 사용하거나
wget
도 사용할 수 있습니다.wget http://127.0.0.1/api/v1/b/watched_files/<File-Name>
도움이 되었기를 바랍니다. 감사!
Reference
이 문제에 관하여(C++로 파일 변경 내역을 유지하는 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/reduct-storage/how-to-keep-a-history-of-file-changes-with-c-17g7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)