Witam mam problem z plikami binarnymi, piszę sobie w ramach ćwiczeń prosty paker
plików czyli kompilacja kilku plików w jeden.
Poczytałem sobie na ten temat. Założyłem, że pierwsze 4 bajty mojego archiwum będą ilością plików w archiwum, kolejne X4 w zależności od ilości plików to wielkości plików, następnie X50 to nazwy. Wszystko działa bardzo fajnie i generalnie jest super, ale program działa tylko dla plików nie większych niż 1kb. Większe niby rozpakowuje(nawet mają odpowiednią wielkość) ale programy które powinny je otwierać informuję o błędach w plikach nie mam pojęcia gdzie może leżeć błąd. Więc zwracam się do was o pomoc.
O to kod:
main.cpp
#include <cstdlib>
#include <iostream>
#include "packer.h"
int main (){
int in;
//std::string in;
std::cin>>in;
Packer* packer;
try{
packer = new Packer("arch.amp");
//std::cout<<packer->getFileSize("red.png")<<std::endl;
//packer->praseInputLine("red.png;green.png;blue.png");
packer->praseInputLine("red.png;green.png;blue.png;mus_maintheme.mp3");
packer->createArchive();
//std::cout<<packer->archiveFileSize(1)<<std::endl;
//packer->unpackArchive();
std::ofstream out("lol.mp3", std::ios::binary);
int count = packer->archiveFilesCount();
int size = packer->archiveFileSize(in);
out.write(packer->archiveFileData(in, count), size);
out.close();
}
catch(std::string e){
std::cout<<e<<std::endl;
}
delete packer;
system("pause");
return 0;
}
packer.cpp:
#include <cstring>
#include <iostream>
#include "packer.h"
Packer::Packer(std::string archivefilename){
archive = archivefilename;
}
void Packer::createArchive(){
outfile.open(archive.c_str(), std::ios::binary);
int i = (int)names.size();
outfile.write((char*)&i, sizeof(i));
for(std::vector<std::string>::iterator it = names.begin(); it != names.end(); it++){
int len = getFileSize(*it);
sizes.push_back(len);
outfile.write((char*)&len, sizeof(len));
}
for(std::vector<std::string>::iterator it = names.begin(); it != names.end(); it++)
outfile.write(std::string(*it).c_str(), 50);
int size = names.size();
for(int i=0; i<size; i++){
infile.open(names[i].c_str(), std::ios::binary);
if(!infile)
throw std::string(names[i] + " not found!");
buf = new char[sizes[i]];
infile.read(buf, sizes[i]);
outfile.write(buf, sizes[i]);
infile.close();
delete[] buf;
}
names.clear();
sizes.clear();
outfile.close();
}
void Packer::unpackArchive(){
getArchiveInfo();
int count = archiveFilesCount();
infile.open(archive.c_str(), std::ios::binary);
for(int i=0; i<count; i++){
std::cout<<"Unpaking file no. "<<i+1<<" name: "<<names[i]<<" size: "<<sizes[i]<<std::endl;
outfile.open(names[i].c_str(), std::ios::binary);
if(i == 0)
infile.seekg((count*sizeof(int))+(count*50));
else
infile.seekg((count*sizeof(int))+(count*50)+sizes[i-1]);
buf = new char[sizes[i]];
infile.read(buf, sizes[i]);
outfile.write(buf, sizes[i]);
infile.seekg(0, std::ios::beg);
delete[] buf;
outfile.close();
}
infile.close();
}
long Packer::getFileSize(std::string name){
infile.open(name.c_str(), std::ios::binary);
if(!infile)
throw std::string(name + " not found!");
long size;
infile.seekg(0, std::ios::end);
size = infile.tellg();
infile.seekg(0, std::ios::beg);
infile.close();
return size;
}
int Packer::archiveFilesCount(){
infile.open(archive.c_str(), std::ios::binary);
if(!infile)
throw std::string(archive + " not found!");
int i;
infile.read((char*)&i, sizeof(i));
infile.close();
return i;
}
char* Packer::archiveFileData(int index, int count){
int size = 0, buflen = 0;
for(int i=1; i<index; i++)
size += archiveFileSize(i);
buflen = archiveFileSize(index);
infile.open(archive.c_str(), std::ios::binary);
if(!infile)
throw std::string(archive + " not found!");
buf = new char[buflen];
std::cout<<buflen<<" "<<size<<std::endl;
std::cout<<(count*sizeof(int))+(count*50)+sizeof(int)+size<<std::endl;
infile.seekg((count*sizeof(int))+(count*50)+sizeof(int)+size);
infile.read(buf, buflen);
infile.seekg(0, std::ios::beg);
infile.close();
delete[] buf;
return buf;
}
std::string Packer::archiveFileName(int index, int count){
infile.open(archive.c_str(), std::ios::binary);
if(!infile)
throw std::string(archive + " not found!");
std::string sbuf;
buf = new char[50];
infile.seekg((count*sizeof(int))+((index-1)*50)+sizeof(int));
infile.read(buf, 50);
infile.seekg(0, std::ios::beg);
infile.close();
sbuf = std::string(buf);
delete[] buf;
return sbuf;
}
int Packer::archiveFileSize(int index){
infile.open(archive.c_str(), std::ios::binary);
if(!infile)
throw std::string(archive + " not found!");
int len;
infile.seekg(index*sizeof(int));
infile.read((char*)&len, sizeof(int));
infile.seekg(0, std::ios::beg);
infile.close();
return len;
}
void Packer::praseInputLine(std::string line){
char str[1024];
sprintf(str, "%s", line.c_str());
char* pch = strtok(str,";");
while(pch != NULL){
names.push_back(std::string(pch));
pch = strtok(NULL, ";");
}
}
void Packer::getArchiveInfo(){
int count = archiveFilesCount();
for(int i=1; i<=count; i++){
names.push_back(archiveFileName(i, count));
sizes.push_back(archiveFileSize(i));
}
}
packer.h:
#ifndef PACKER_H
#define PACKER_H
#include <string>
#include <vector>
#include <fstream>
class Packer{
public:
Packer(std::string name);
~Packer(){};
void praseInputLine(std::string);
long getFileSize(std::string);
void createArchive();
void unpackArchive();
int archiveFilesCount();
std::string archiveFileName(int, int);
int archiveFileSize(int);
void getArchiveInfo();
char* archiveFileData(int, int);
private:
char* buf;
std::string archive;
std::ifstream infile;
std::ofstream outfile;
std::vector<std::string>names;
std::vector<int>sizes;
};
#endif //PACKER_H
Z góry dziękuję i pozdrawiam,
Miziak.