Created
March 16, 2023 06:41
-
-
Save devymex/08309b267b8b9504e828d1181cdfcbbe to your computer and use it in GitHub Desktop.
Compares two files to find differences, then fixes the second file to be identical with the first. Useful when copying a large file between two storage devices.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <algorithm> | |
#include <cstring> | |
#include <fstream> | |
#include <iostream> | |
template<typename _Stream> | |
size_t GetFileSize(_Stream &stream) { | |
auto nCurPos = stream.tellg(); | |
stream.seekg(0, std::ios::end); | |
auto nFileSize = stream.tellg(); | |
stream.seekg(nCurPos, std::ios::beg); | |
return nFileSize; | |
} | |
int main(int nArgCnt, char *ppArgs[]) { | |
std::ifstream src(ppArgs[1], std::ios::binary); | |
auto nFileSize = GetFileSize(src); | |
std::fstream dst(ppArgs[2], std::ios::binary | std::ios::in | std::ios::out); | |
if (nFileSize != GetFileSize(dst)) { | |
std::cout << "Size not equal" << std::endl; | |
return -1; | |
} | |
size_t nChunkSize = 1024 * 1024 * 1024; | |
size_t nChunks = (nFileSize + nChunkSize - 1) / nChunkSize; | |
std::string strSrcBuf, strDstBuf; | |
for (size_t i = 0; i < nChunks; ++i) { | |
size_t nReadBeg = i * nChunkSize; | |
size_t nReadEnd = std::min(nFileSize, (i + 1) * nChunkSize); | |
size_t nReadSize = nReadEnd - nReadBeg; | |
strSrcBuf.resize(nReadSize); | |
strDstBuf.resize(nReadSize); | |
std::cout << "Reading chunk " << i << std::endl; | |
dst.seekg(nReadBeg, std::ios::beg); | |
if (!src.read(const_cast<char*>(strSrcBuf.data()), strSrcBuf.size()) || | |
!dst.read(const_cast<char*>(strDstBuf.data()), strDstBuf.size())) { | |
std::cout << "Read Failed!" << std::endl; | |
return -1; | |
} | |
std::cout << "Comparing chunk " << i << std::endl; | |
if (std::memcmp(strSrcBuf.data(), strDstBuf.data(), nReadSize) != 0) { | |
for (size_t j = 0; j < nChunkSize; ++j) { | |
if (strSrcBuf.data()[j] != strDstBuf.data()[j]) { | |
auto nPos = nReadBeg + j; | |
std::cout << "Make same at [" << nPos << "] " << (int)strSrcBuf[j] | |
<< " vs " << (int)strDstBuf[j] << std::endl; | |
dst.seekp(nPos); | |
dst.write(&strSrcBuf[j], 1); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment