Ich stell das mal online.
Wenn es euch interessiert könnt ihr es euch ja mal ansehen
Aufgabe:
Erstellt aus mehreren (per Kommandozeilenparameter) angegebenen Dateien (Ordner anzugeben ist NICHT möglich!) eine einzige Datei.
Die Dateien werden in keinster Weise verändert/komprimiert/o.ä.
Das Programm speichert in die neue Datei, die sog. Resourcedatei, wieviele Dateien in ihr enthalten sind, wo sie beginnen (relativ zum Ende des Headers) und natürlich die Datei selbst mit Dateinamen.
Es können wegen dynamisch großen Addressierungen auch relativ große Dateien gespeichert werden.
Was noch fehlt:
Unterstützung für Ordner
Programm, um die Dateien wieder herrauszubekommen (^^)
Ich übernehme wie immer keine Verantwortung für Schäden, die das Programm anrichtet.
Auch wenn das Programm natürlich nicht darauf ausgerichtet ist, Schäden anzurichten.
Bei Fragen und Bugs: Raus damit!
MfG
Daniel
main.cpp
Code: Alles auswählen
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <iostream>
#include <cstdlib>
using namespace std;
#include "def1.h"
#include "func1.h"
int main(int argc, char *argv[])
{
int Files_to_pack = 0;
int ParamFiles_Count = argc -1;
packmf2 *packme;
/*INTRO UND PARAMETERÜBERPÜRFUNG*/
cout << "*- Resource File Generator - 2nd Version -*\n" << endl;
cout << "Anzahl an Dateien zu packen: " << ParamFiles_Count << endl;
if (ParamFiles_Count <= 0) {
cout << "SORRY, aber ohne Dateien geht's nicht..." << endl;
exit(-1);
}
/*ÜBERPRÜFUNG DER DATEIEN*/
cout << "-----Dateien:-----" << endl;
for (int i=0; i<ParamFiles_Count; i++) {
cout<< i+1 << " ";
if (Filecanbeopend(argv[i+1])) {
cout << " OK ";
Files_to_pack++;
} else {
cout << "NOPE ";
}
cout << argv[i+1] << endl;
}
cout << "------------------" << endl;
cout << "Verfügbare Dateien: " << Files_to_pack << endl;
if (Files_to_pack<=0) {
cout << "SORRY, keine Daten verfügbar..." << endl;
exit(-1);
}
/*DATEIARRAY MIT INFOS ERZEUGEN*/
cout << "Erzeuge Dateiarray..." << endl;
packme = new packmf2[Files_to_pack];
int tmp = 0;
for (int i=0; i<ParamFiles_Count; i++) {
cout<< i+1 << " ";
if (Filecanbeopend(argv[i+1])) {
cout << "GETS PACKED ";
packme[tmp].name = argv[i+1];
packme[tmp].filesize = GetFileSize(packme[tmp].name.c_str());
packme[tmp].file.open(packme[tmp].name.c_str());
tmp++;
if (tmp>Files_to_pack) {
cout << "SORRY, irgendwas ist hier ordentlich schief gelaufen...";
exit(-1);
}
cout << "Arrayeintrag erfolgreich eingetragen" << endl;
} else {
cout << "NOT TO PACK Kein Arrayeintrag nötig" << endl;
}
}
cout << CreateResourceFile(packme,Files_to_pack);
for (int i=0;i<Files_to_pack;i++) {
cout << "Schließe Datei Nr." << i+1;
packme[i].file.close();
cout << " OK!" << endl;
}
delete [] packme;
return 1;
}
Code: Alles auswählen
#ifndef __RFG_V2_DEF1_H_
#define __RFG_V2_DEF1_H_
#include <fstream>
#include <string>
#define BYTES(x) (x)
#define KBYTES(x) (x*1024)
typedef class __packme_file_v2
{
private:
public:
unsigned long filesize;
//int namesize;
string name;
fstream file;
}packmf2;
typedef char Byte;
#endif
Code: Alles auswählen
#ifndef __RFG_V2_FUNC1_H_
#define __RFG_V2_FUNC1_H_
#include <fstream>
#include <string>
#include "def1.h"
#define BIT_N(x) (base_exponent(x,2))
// Bit: 7 6 5 4 3 2 1 0
// 7,6,5 = Versionsnummer (0=Version1, 1=Version2, etc)
// 4 = Gepackt? (1 = Ja)
// 3 = Verschlüsselt? (1 = Ja)
// 2 = Viele/Wenige Dateien (mehr als 256 ?) (1 = Ja)
// 1,0 = Unbenutzt
#define _VERSION_I_V2 (BIT_N(5))
#define _VERSION_I_PACKED (BIT_N(4))
#define _VERSION_I_M256 (BIT_N(2))
unsigned long base_exponent(short exp, short base);
unsigned long GetFileSize(string filename);
short Filecanbeopend(string filename);
short CreateResourceFile(packmf2 *Packarray, int File_Count)
{
fstream ResFile;
ResFile.open("ResFile.rf2", ios_base::in | ios_base::out | ios_base::binary | ios_base::trunc );
if (ResFile == NULL) {
return -1;
}
//
/*HEADER*/
unsigned char VersionInfo = 0;
VersionInfo = _VERSION_I_V2 | 0;
if (File_Count > 256) {
VersionInfo |= _VERSION_I_M256;
if (File_Count > 65536) {
return -1;
}
}
ResFile.write((const char*)&VersionInfo,BYTES(1));
if (File_Count <= 256) {
ResFile.write((const char*)&File_Count,BYTES(1));
} else {
ResFile.write((const char*)&File_Count,BYTES(2));
}
short EndofInfo = ResFile.tellp();
unsigned long tmp = 0;
unsigned long tmp2 = 0;
int extra_bytes = 0;
ResFile.write((const char*)&tmp,BYTES(1)); // tmp= 0 => 0 Bytes extra=> Start an 0
/* Aufbau:
Byte 1 | 7 6 5 4 3 2 1 0
// Bit 7-3 : Anzahl Bytes (max 32)
// Bit 2,1,0 : Positionsbits (wenn mehr Bytes, dann die ersten)
//Byte 2,3,... : weitere Positionsbits
*/
for (int i=1; i<File_Count; i++) {
// Wo kommt der neue Header hin?
tmp += Packarray[i-1].filesize; //Datei muss rein
tmp += (1); //Speicher für Anzahl Zeichen im Namen der Datei muss rein
tmp += Packarray[i-1].name.length();// Speicher für den Namen
if (tmp < 8) {
tmp2 = (tmp & 7);
ResFile.write((const char*)&tmp2,BYTES(1));
} else {
extra_bytes = 1;// Ein weiteres Byte
tmp2 = 0;
while (tmp2 < tmp) {// Kann ich genügend Bytes addressieren?
tmp2 = (base_exponent( (3+extra_bytes*8), 2)); // Wieviele Bytes kann ich addressieren?
extra_bytes++;// Also noch eins
}
extra_bytes--;// Damits stimmt.
if (extra_bytes > 32) {
cout << "SO VIEL SPEICHER GIBT ET NET!!";
exit(-1);
}
tmp2 = 0;
tmp2 = (extra_bytes << 3); //Anzahl an zusätzlichen Bytes speichern
tmp2 |= (tmp) >> ((3+extra_bytes*8)-3);//Erste 3 Bits der Position speichern
ResFile.write((const char*)&tmp2,BYTES(1));//Ab in die Datei
ResFile.write((const char*)&tmp,BYTES(extra_bytes));//Restliche Bytes mit Position schreiben
}
}
unsigned long header_end = ResFile.tellp();
/* HEADER-ENDE */
/* BODY */
tmp = 0;
tmp2 = 0;
char buff = 0;
for (int i=0; i<File_Count; i++) {
tmp = Packarray[i].name.length();//Speichere Dateinamengröße
ResFile.write((const char*)&tmp,BYTES(1));//und schreibe in Datei (max Dateinamengröße=2^8=256)
ResFile.write((const char*)Packarray[i].name.c_str(),BYTES(tmp));
buff = 0;
while (Packarray[i].file.good()) {
Packarray[i].file.read((char*)&buff,BYTES(1));
ResFile.write((const char*)&buff,BYTES(1));
}
}
/* BODY-ENDE */
tmp = BIT_N(7) | BIT_N(5) | BIT_N(3) | BIT_N(1);//Signatur ( 1 0 1 0 1 0 1 0 )
ResFile.write((const char*)&tmp,BYTES(1));
ResFile.close();
return 0;
}
/**
* Gibt die Dateigröße in Form eines Longwertes zurück. Einheit ist Bytes.
* @param filename: Der Dateiname
* @return size: Größe der Datei in Bytes
*/
unsigned long GetFileSize(string filename)//in Byte
{
unsigned long size = 0;
fstream file;
file.open(filename.c_str(),ios_base::in | ios_base::out);
if (file==NULL) {
return 0;
}
file.seekg(0,ios::end);
size = file.tellg();
file.close();
return size;
}
/**
* Überprüft ob die angegebene Datei geöffnet/gelesen werden kann
* @param filename : Der Dateiname
* @return 1, wenn Datei geöffnet werden kann, ansonsten 0
*/
short Filecanbeopend(string filename)
{
fstream file;
file.open(filename.c_str());
if (file==NULL) {
return 0;
} else {
file.close();
return 1;
}
}
/**
* Gibt Basis hoch Exponent zurück. Nur gerade Exponenten werden unterstützt. Achtung bei großen Zahlen!
* @param exp : Exponent
* @param base : Basis
* @return result : Basis hoch Exponent
*/
unsigned long base_exponent(short exp, short base)
{
unsigned long result = 1;
for (short i=0; i < exp; i++) {
result *= base;
}
return result;
}
#endif