on my initial attempt of creating a duplicate files finder(see Duplicate files finder in C++ @ this code review site) I have finally came across the successful and optimized implementation of this code. The idea is same like the but I have made changes according to the advice of some professional here and also have fixed some bugs. Tangerine.cpp
// SWAMI KARUPPASWAMI THUNNAI
// Tangerine.cpp : Defines the entry point for the console application.
// Programmed by VISWESWARAN N (C), 2016
#include<iostream>
#include<fstream>
#include<Windows.h>
#include<string>
#include"scan.h"
int main()
{
std::cout << "Tangerine Solutions\n";
std::string location;
std::cout << "Enter the location :" << std::endl;
getline(std::cin, location);
Process process;
process.scan(location);
int stay;
std::cin >> stay;
return 0;
}
scan.h
#pragma once
#include<iostream>
#include<string>
#include<map>
#include<list>
#include<map>
#include<list>
#include"preliminary.h"
// Processing the files
class Process:public PreliminaryTest
{
public:
bool scan(std::string location);
double getSize(std::string location);
};
scan.cpp
#include<iostream>
#include<conio.h>
#include<fstream>
#include<Windows.h>
#include<boost\filesystem.hpp>
#include"scan.h"
namespace v = boost::filesystem;
bool Process::scan(std::string location)
{
for (v::recursive_directory_iterator end, file(location); file != end; ++file)
{
if (file->status().type() != v::regular_file) std::cout << "|| System file has been found skipping\n";
else
{
std::string loc = file->path().string(); // We will get the location
std::cout << "|| Processing " << loc << "\n";
std::cout << "|| SIZE: " << getSize(loc) << "\n";
std::cout << "|| Performing the preliminary test...\n";
double size_of_current_file = getSize(loc);
start_preliminary_test(size_of_current_file, loc);
}
}
send_the_report_for_confirmatory_test();
return true;
}
double Process::getSize(std::string location)
{
std::ifstream in;
in.open(location, std::ifstream::ate | std::ifstream::binary);
double size = in.tellg();
return size;
}
preliminary.h
// SWAMI KARUPPASWAMI THUNNAI
#pragma once
#include"headers.h"
class PreliminaryTest:public ConfirmatoryTest
{
private:
// This map is used to identify files with same sizes
std::map<double, std::string> preliminary_tester;
// This list will contain the files with same sizes
std::list<std::string> preliminary_result;
public:
bool start_preliminary_test(double size,std::string location);
void send_the_report_for_confirmatory_test();
};
preliminary.cpp
// SWAMI KARUPPASWAAMI THUNNAI
#include"headers.h"
bool PreliminaryTest::start_preliminary_test(double size,std::string location)
{
std::map<double, std::string>::iterator test;
test = preliminary_tester.find(size);
if (test != preliminary_tester.end())
{
// List of files with same sizes
std::cout << "\n Files with similar sizes have been found\n";
preliminary_result.push_back(location);
preliminary_result.push_back(test->second);
std::ofstream file;
file.open("SAME SIZED FILES.txt",std::ios::app);
file << location << "\n";
file << test->second << "\n";
file.close();
}
else preliminary_tester[size] = location;
}
void PreliminaryTest::send_the_report_for_confirmatory_test()
{
// Use iterators to access to the algorithms
// I know this is lengthy but this is standard for almost all STL containers like deque, vectors etc.,
// This method is called half open and closed iterators
// itr = iterators which links algo to the container
std::list<std::string>::iterator itr1 = preliminary_result.begin();
std::list<std::string>::iterator itr2 = preliminary_result.end();
for (std::list<std::string>::iterator itr = itr1; itr != itr2; ++itr)
{
std::cout << "\nSending the result for confirmatory test...\n";
preliminary_test_result.push_back(*itr);
std::cout << *itr;
}
std::list<std::string>::iterator itr3 = preliminary_test_result.begin();
std::list<std::string>::iterator itr4 = preliminary_test_result.end();
for (std::list<std::string>::iterator itr = itr3; itr != itr4; ++itr)
{
std::cout << "\nProcessing confirmatory test...\n";
std::cout << *itr;
confirm(*itr);
}
}
confirmatory.h
// SWAMI KARUPPASWAMI THUNNAI
#pragma once
#include"headers.h"
class ConfirmatoryTest
{
private:
// Map to identify the hash matching
std::map<std::string, std::string> confirmatory_tester;
// Final Neat and Clean list of the locations of duplicate files are been stored here
std::list<std::string> confirmatory_result;
// The Member of This access specifier is used between member function of different class - so no provate
protected:
std::list<std::string> preliminary_test_result;
public:
std::string get_hash_for(const std::string location);
void confirm(std::string location);
};
confirmatory.cpp
// SWAMI KARUPPASWAMI THUNNAI
#include"md5.h"
#include "headers.h"
std::string ConfirmatoryTest::get_hash_for(const std::string location)
{
// I know this the below line may be omitted but it adds clarity
std::string current_location = location;
char* processed_location = new char[current_location.length() + 1];
strcpy(processed_location, location.c_str());
std::cout << "\n\n\n===>" << location;
std::string md5;
md5 = CALL_MD5_Function(processed_location);
delete[] processed_location; // it is important to free up the memory
return md5;
}
void ConfirmatoryTest::confirm(std::string location)
{
std::string current_hash;
current_hash = get_hash_for(location);
std::map<std::string, std::string>::iterator test;
test = confirmatory_tester.find(current_hash);
if (test != confirmatory_tester.end())
{
confirmatory_result.push_back(location);
confirmatory_result.push_back(test->second);
// Some logging will help to identify the problem
std::ofstream file;
file.open("DUPLICATES.txt", std::ios::app);
file << location << "\n";
file << test->second << "\n";
file.close();
}
else
{
// This will save the current hash and locations
confirmatory_tester[current_hash] = location;
}
}
headers.h - came accross with a LNK2005 error so I have used this
#pragma once
#include<iostream>
#include<string>
#include<map>
#include<list>
#include<map>
#include<list>
#include<fstream>
#include"confirmatory.h"
#include"preliminary.h"
ADVANTAGES 1. The previous one is windows dependent and this is capable of running in on any platform (cross-platformed)
The previous one gained insane access to all system files when a manifest file is added but this could only scan the regular file
Two way processing check file size and then compute hashes so time is greatly reduced!
Every single bug has been fixed proper duplicate file location are stored in a DUPLICATES.txt file
The initial code made used of an answer posted by the professional here which causes several license issue finally I've found my own solution so now I can happily host this on GitHub :) https://github.com/VISWESWARAN1998/Tangerine-Duplicate-Files-Finder
I am a student and I will keep all the advices you drop here you can find that I have improved my code with previous answers and comments posted by the professionals like not used namespace std, endl, using const etc and etc so kindly inform the areas where I have to improve this code so that I can learn from you and gain knowledge and use on my future work :) Thank you