Evo jednog resenja datog problema:
Ideja je da citas iz binarno sortiranog fajla, a da on istovremeno bude spakovan. Stepen kompresije nije toliko bitan, a u mom konkretnom primeru od jednog fajla dobijemo dva, dok velicinu smanjimo za nesto vise od pola. Negativne strane ove metode su da se pakovanje ne vrsi kroz ceo fajl, nego je svaki podatak zapakovan sam za sebe. Time smo mogucu kompresiju smanjili desetak puta (ovo je bazirano na konkretnim merenjima, za razlicite podatke ce se dobijati razliciti podaci).
Funkcija koja pakuje vektor i smesta ga u fajl, dok istovremeno pravi drugi fajl sa elementima koji sluze za pretragu:
Code:
void packAndSaveData(vector<Junction>& vec){
string dpath = "putanja do fajla za pretragu";
string fpath = "putanja do fajla sa zapakovanim podacima";
ofstream ofsd(dpath.c_str(), ios::binary);
ofstream ofsf(fpath.c_str(), ios::binary);
int placeInFile = 0;
//Pravljenje isfoliranog pointera koji sluzi da na pocetku fajla imamo ukupan broj elemenata, cime ubrzavamo binarnu pretragu
fPositioner fp1;
fp1.file = vec.size();
fp1.ID = 0;
fp1.placeInFile = 0;
fp1.packedSize = 0;
fp1.unpackedSize = 0;
ofsd.write((char*) &fp1, sizeof fPositioner);
for(int i=0; i<vec.size(); i++){
Junction jnc = vec.at(i);
int orgSize = sizeof Junction;
BYTE* orgData = (BYTE*) malloc (orgSize);
memcpy(orgData, &jnc, orgSize);
ULONG comSize = (ULONG) (orgSize * 1.1 + 20);
BYTE* compData = (BYTE*) malloc(comSize);
//
compress(compData, &comSize, orgData, orgSize);
//
fPositioner fp;
fp.file = 1;
fp.ID = jnc.ID;
fp.placeInFile = placeInFile;
fp.packedSize = comSize;
fp.unpackedSize = orgSize;
placeInFile += fp.packedSize;
ofsd.write((char*) &fp, sizeof fPositioner);
ofsf.write((char*) compData, fp.packedSize);
}
ofsd.close();
ofsf.close();
}
Ovde je ubaceno nekoliko nepotrebnih stvari u fPositioner, koje ce sluziti za neke druge stvari, posto mi se ne pravi tona slicnih struktura. Kad smo vec kod toga, ovako izgleda fPositioner:
Code:
struct fPositioner{
int file;
int placeInFile;
int packedSize;
int unpackedSize;
int ID;
};
Naravno, umesto njega se moze koristiti i bilo koja slicna struktura sa nekoliko brojeva u sebi. Isto tako ce raditi i sa nizom intova...
Kad smo zapakovali fajl gornjom funkcijom, ovako pronalazimo element sa trazenim ID-jem:
Code:
Junction getJunction(int ID){
ifstream ifsd(dpath.c_str(), ios::binary);
filePositioner pos;
ifsd.read((char*) &pos, sizeof fPositioner);
int first=1, last = pos.file; //Ovo je onaj element koji ne sluzi nicemu drugom, nego vadjenju broja elemenata sa pocetka fajla
while (first <= last){
int mid = (first + last) / 2; // compute mid point.
ifsd.seekg(mid * sizeof fPositioner);
ifsd.read((char*) &pos, sizeof fPositioner);
if (ID > pos.ID){
first = mid + 1; // repeat search in top half.
}
else if (ID < pos.ID){
last = mid - 1; // repeat search in bottom half.
}
else { break; }
}
ifsd.close();
ULONG finalSize = pos.unpackedSize;
BYTE* freadData = (BYTE*) malloc(pos.packedSize);
BYTE* finalData = (BYTE*) malloc(pos.unpackedSize);
ifstream ifsf(fpath.c_str(), ios::binary);
ifsf.seekg(pos.placeInFile);
ifsf.read((char*) freadData, pos.packedSize);
ifsf.close();
//
uncompress(finalData, &finalSize, freadData, pos.packedSize);
//
Junction temp;
memcpy(&temp, finalData, finalSize);
return temp;
}
I to vam je to. Nadam se da ce neko naci poneku glupost u kodu, a nemam nista protiv ni da mi se ukaze na strukturalne nepravilnosti (ili bolji nacin obavljanja ovog posla). Inace, ovo provereno radi, a za one kojima bi mozda posluzio ovaj kod, samo da kazem da se moze koristiti za bilo sta, samo rec "Junction" promenite u ime neke svoje strukture.
De si Deda...