Thanks alot for that formula CornedBee, i've implemented it now, and i'm pretty sure it's working as it is supposed to.
I've also added error checking for all the Win32 functions that i am calling, and it's returning the right error codes aswell. Oh and i've added a try catch block around the new operator aswell. All that is left now is to comment the code properly, as it is now it is very confusing, even for me, and i'm the one who wrote it.
Code:
#include <windows.h>
#include <iostream>
#include <string>
#include <sstream>
#include <exception>
int main(int argc, char* argv[])
{
if(argc != 3)
{
std::cerr << "Invalid number of arguments, "
<< "Correct usage is: split FILEPATH NUMBEROFOUTPUTFILES" << std::endl;
return 1;
}
DWORD FileCount = strtol(argv[2], NULL, 10);
if(FileCount <= 0)
{
std::cerr << "Divison by 0!! BOOM the world just collapsed, try again..." << std::endl;
return 1;
}
HANDLE hFile = CreateFile(argv[1], GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
std::cerr << "Error " << GetLastError() << " occured." << std::endl;
return 1;
}
char *pBuffer = NULL;
std::string OutputFileName;
std::stringstream ss (std::stringstream::in | std::stringstream::out); // Used for converting 'i' to a std::string
DWORD InputSize = GetFileSize(hFile, NULL);
if(InputSize == INVALID_FILE_SIZE)
{
std::cerr << "Error " << GetLastError() << " occured." << std::endl;
return 1;
}
DWORD BaseOutSize = InputSize / FileCount;
DWORD Remainder = InputSize % FileCount;
try
{
pBuffer = new char[BaseOutSize+1];
}
catch (std::bad_alloc&)
{
std::cerr << "Error allocating memory." << std::endl;
return 1;
}
std::cout << "File size is: " << InputSize << " bytes." << std::endl;
std::cout << "Splitting into " << FileCount << " files - " << BaseOutSize << " bytes each." << std::endl;
DWORD dwBytesRead, lpNumberOfBytesWritten; //Necessary to avoid Segfaults
for(DWORD i = 0; i < FileCount; i++)
{
ss.str("");
ss << "PART" << i+1 << argv[1];
OutputFileName = ss.str();
HANDLE OutputHandle;
DWORD CurrentFileSize = BaseOutSize + ((i < Remainder) ? 1 : 0);
if(!ReadFile(hFile, pBuffer, CurrentFileSize, &dwBytesRead, NULL))
{
std::cerr << "Error " << GetLastError() << " occured." << std::endl;
return 1;
}
OutputHandle = CreateFile(OutputFileName.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
if(OutputHandle == INVALID_HANDLE_VALUE)
{
std::cerr << "Error " << GetLastError() << " occured." << std::endl;
return 1;
}
if(!WriteFile(OutputHandle, pBuffer, CurrentFileSize, &lpNumberOfBytesWritten, NULL))
{
std::cerr << "Error " << GetLastError() << " occured." << std::endl;
return 1;
}
if(!CloseHandle(OutputHandle))
{
std::cerr << "Error " << GetLastError() << " occured." << std::endl;
return 1;
}
}
if(!CloseHandle(hFile))
{
std::cerr << "Error " << GetLastError() << " occured." << std::endl;
return 1;
}
delete[] pBuffer;
return 0;
}
I'm still using GetFileSize, because when i try to use GetFileSizeEx instead it just says that it is an undeclared function. I'm not sure why, because MSDN says it is defined in winbase.h, which is included in windows.h. I've also tried explicitly including winbase.h, but it's still the same?
I think i'm pretty much done now then?