/*
Console File Splitter v 0.2
Divide i file in più parti e all'occorrenza li ricompone.
Utile per qualsiasi esigenza di spazio.
Autore: __GiReX__
Linguaggio: C++
Sistema operativo: Qualsiasi
Data: 26/11/07 20.47
Sito: http://girex.altervusta.org/
*/
#include <iostream>
#include <fstream>
#include <cstring>
#include <ctime>
#include <cmath>
#define SPLIT_SUCCESS 0
#define MERGE_SUCCESS 4
using namespace std;
void usage(char *prog);
int split(char *nome_file, int parti);
int merge(char *nome_file, int parti);
int name_part(int n_part, char *nome_file, char *tmp);
int main(int argc, char *argv[])
{
int parti, error;
clock_t sec;
char *nome_file = NULL;
if(argc < 3 || argc > 4) {
usage(argv[0]);
return 1;
}
if(argc == 4 && strcmp(argv[1], "-r")) {
cout << "\n\"" << argv[1] << "\" Parametro non riconosciuto!\n\n";
usage(argv[0]);
return 2;
}
if(argc == 3) {
nome_file = argv[1];
parti = atoi(argv[2]);
error = split(nome_file, parti); // Splitto
} else {
nome_file = argv[2];
parti = atoi(argv[3]);
error = merge(nome_file, parti); // Mergo
}
sec = clock() / CLOCKS_PER_SEC;
switch(error) {
case SPLIT_SUCCESS:
cout << "Il file e' stato diviso in " << parti << " parti con successo!\n\n"
<< "Tempo impiegato: " << sec << " sec\n";
break;
case 1:
cout << "Errore nell'apertura del file!\n\n"
<< "Controllare che il nome o percorso siano corretti!\n";
break;
case 2:
cout << "Errore: Numero di parti troppo elevato!\n";
break;
case 3:
cout << "Errore nella creazione dei file part!\n";
break;
case -1:
cout << "Errore nella creazione del file di destinazione!\n\n"
<< "Controllare che il file originale non risieda nella stessa cartella!";
break;
case -2:
cout << "Impossibile aprire i file part!\n\n"
<< "Controllare che il nome del file corrisponda al nome del file originario\n"
<< "e che il numero di parti dichiarato corrisponda!\n";
break;
case MERGE_SUCCESS:
cout << "Il file e' stato ricomposto con successo!\n\n"
<< "Tempo impiegato: " << sec << " sec\n";
break;
default:
cout << "Errore sconosciuto!\n";
}
cout << "\nPremere un tasto per uscire...\n";
cin.ignore();
return 0;
}
int name_part(int n_part, char *nome_file, char *tmp)
{
char buff[4] = {0};
strcpy(tmp, nome_file);
strcat(tmp, ".part_");
strcat(tmp, itoa(n_part, buff, 10)); // Funzione per convertire int to char*
return 0;
}
int split(char *nome_file, int parti)
{
ifstream *file = new ifstream(nome_file,ios::binary);// Apro file in modalità binaria
ofstream *file_part = new ofstream;
long double size, byte_file, last_file_size; // Byte del file, e byte per ogni file
char nome_file_part[80] = {0}; // Nome dei file part
if(!file) return 1;
file->seekg(0, ios::end);
size = file->tellg(); // Prendo lunghezza file
cout << "\nFile di: " << size << " byte" << endl;
if(size < parti*2 || parti > 30) return 2;
file->seekg(0, ios::beg); // Risposto il cursore all'inizio del file
byte_file = ceil(size / parti); // Byte per ogni file part arrotondati per eccesso
last_file_size = (size - (byte_file*parti)) + byte_file; // Byte dell'ultimo file che differisce dagli altri
cout << "Splitting in corso...\n";
for(int i = 0; i < parti; i++) {
name_part(i, nome_file, nome_file_part); // Prendo nome dei file part
file_part->open(nome_file_part, ios::binary); // Apro i file in modalità binaria
if(!file_part) return 3;
if( i == (parti - 1)) { // Se è l'ultimo file..
for(register int i2 = 0; i2 < last_file_size; i2++)
file_part->put(file->get());
} else {
for(register int i2 = 0; i2 < byte_file; i2++)
file_part->put(file->get()); // Un byte alla volta copio n byte per file nel file part
}
file_part->close();
}
file->close();
return SPLIT_SUCCESS;
}
int merge(char *nome_file, int parti)
{
char bit, nome_part[80] = {0};
ofstream *file = new ofstream(nome_file, ios::binary);
ifstream *file_part = new ifstream;
if(!file) return -1;
cout << "\nRicomponimento (merge) in corso...\n";
for(int i = 0; i < parti; i++) {
name_part(i, nome_file, nome_part); // Prendo il nome dei file part
file_part->open(nome_part, ios::binary); // Apro i file part
if(!file_part) return -2;
while(!file_part->eof()) { // Se npn è un eofbit lo copio nel file
file_part->get(bit);
if(!(file_part->rdstate() & ifstream::eofbit)) file->put(bit); // Copio i file part nel file di destinazione
}
file_part->clear();
file_part->close(); // Chiudo file part
}
file->close();
return MERGE_SUCCESS;
}
void usage(char *prog)
{
cout << "Usage:\n\n"
<< "Per dividere: " << prog << " <file_da_dividere> <numero_parti>\n\n"
<< "Per ricomporre: " << prog << " -r <file_origine> <numero_parti>\n\n"
<< "Dove <file_origine> e' il nome del file che e' stato diviso\n"
<< "e <numero_parti> le parti in cui e' stato diviso!\n";
}