Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!
Werbeanzeige
Administrator
C-/C++-Quelltext |
|
1 2 3 4 5 |
int readArchivedFile(const std::string& archiveFilename, const std::string& filename, const std::string& password, void** pp_dataOut, unsigned int* p_dataSizeOut); |
C-/C++-Quelltext |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
int readArchivedFile(const std::string& archiveFilename, const std::string& filename, const std::string& password, void** pp_dataOut, unsigned int* p_dataSizeOut) { // Archiv öffnen unzFile archive = unzOpen(archiveFilename.c_str()); if(!archive) { // Fehler! Die Archivdatei existiert wahrscheinlich nicht oder ist beschädigt. return -1; } // die archivierte Datei aufspüren, Groß-/Kleinschreibung ignorieren int result = unzLocateFile(archive, filename.c_str(), 0); if(result != UNZ_OK) { // Fehler! Die Datei wurde wohl nicht gefunden. unzClose(archive); return -2; } // Dateiinformationen abfragen unz_file_info info; unzGetCurrentFileInfo(archive, &info, 0, 0, 0, 0, 0, 0); // die entsprechende Menge an Speicher reservieren unsigned int fileSize = static_cast<unsigned int>(info.uncompressed_size); char* p_data = new char[fileSize]; if(!p_data) { // Fehler! Nicht genug Speicher. Die Datei müsste stückweise gelesen werden. unzClose(archive); return -3; } // Datei öffnen - mit Passwort oder ohne if(password.empty()) result = unzOpenCurrentFile(archive); else result = unzOpenCurrentFilePassword(archive, password.c_str()); if(result != UNZ_OK) { // Fehler! Das Passwort könnte falsch sein. delete[] p_data; unzClose(archive); return -4; } // die komplette Datei lesen unsigned int numBytesRead = unzReadCurrentFile(archive, p_data, fileSize); if(numBytesRead != fileSize) { // Fehler! Das Archiv könnte beschädigt sein. delete[] p_data; unzCloseCurrentFile(archive); unzClose(archive); return -5; } // aufräumen unzCloseCurrentFile(archive); unzClose(archive); // Daten und Größe zurückliefern if(pp_dataOut) *pp_dataOut = p_data; if(p_dataSizeOut) *p_dataSizeOut = fileSize; // Alles OK! return 0; } |
C-/C++-Quelltext |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
void* p_text = 0; unsigned int textSize = 0; // verschlüsselte Datei "test.txt" aus dem Archiv "test.zip" lesen, Passwort "1337" int result = readArchivedFile("test.zip", "test.txt", "1337", &p_text, &textSize); if(result) { // Fehler! printf("Fehler! (Code: %d)\n", result); } else { // Text ausgeben std::string text(static_cast<char*>(p_text), textSize); printf("Der gelesene Text: %s\n", text.c_str()); // Speicher wieder freigeben delete[] p_text; } |
C-/C++-Quelltext |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
#pragma pack(push, 1) int deleteArchivedFile(const std::string& archiveFilename, const std::string& objectName) { int result = 0; struct LocalFileHeader { unsigned int signature; unsigned short versionNeeded; unsigned short flags; unsigned short method; unsigned short modTime; unsigned short modDate; unsigned int crc; unsigned int compressedSize; unsigned int uncompressedSize; unsigned short filenameLength; unsigned short extraFieldLength; }; struct EndOfCentralDirectory { unsigned int signature; unsigned short thisDisk; unsigned short centralRecordDisk; unsigned short entriesOnThisDisk; unsigned short totalEntries; unsigned int centralDirectorySize; unsigned int centralDirectoryOffset; unsigned short globalCommentLength; }; struct CentralDirectoryEntry { unsigned int signature; unsigned short versionMadeBy; unsigned short versionNeeded; unsigned short flags; unsigned short method; unsigned short modTime; unsigned short modDate; unsigned int crc; unsigned int compressedSize; unsigned int uncompressedSize; unsigned short filenameLength; unsigned short extraFieldLength; unsigned short commentLength; unsigned short diskNumber; unsigned short intAttribs; unsigned int extAttribs; unsigned int localHeaderOffset; }; FILE* p_in = fopen(archiveFilename.c_str(), "rb"); FILE* p_out = fopen((archiveFilename + "_").c_str(), "wb"); // zentrales Verzeichnis suchen while(true) { unsigned int signature; unsigned int pos = ftell(p_in); fread(&signature, 1, 4, p_in); fseek(p_in, pos, SEEK_SET); if(signature == 0x04034B50) { LocalFileHeader lfh; fread(&lfh, 1, sizeof(lfh), p_in); fseek(p_in, lfh.filenameLength + lfh.extraFieldLength + lfh.compressedSize, SEEK_CUR); } else if(signature == 0x02014B50) { CentralDirectoryEntry cde; fread(&cde, 1, sizeof(cde), p_in); fseek(p_in, cde.filenameLength + cde.extraFieldLength + cde.commentLength, SEEK_CUR); } else if(signature == 0x06054B50) { // Danach haben wir gesucht! break; } else { return false; } } EndOfCentralDirectory ecd, ecdOut; fread(&ecd, 1, sizeof(ecd), p_in); char* p_globalComment = 0; if(ecd.globalCommentLength) p_globalComment = new char[ecd.globalCommentLength]; ecdOut = ecd; fseek(p_in, ecd.centralDirectoryOffset, SEEK_SET); std::vector<CentralDirectoryEntry> cdOut; std::vector<char*> filenameOut, extraFieldOut, commentOut; // Einträge lesen und schreiben for(unsigned int i = 0; i < ecd.totalEntries; i++) { CentralDirectoryEntry cde, cdeOut; fread(&cde, 1, sizeof(cde), p_in); cdeOut = cde; char* p_filename = new char[cde.filenameLength + 1]; fread(p_filename, 1, cde.filenameLength, p_in); p_filename[cde.filenameLength] = 0; char* p_extraField = 0; if(cde.extraFieldLength) { p_extraField = new char[cde.extraFieldLength]; fread(p_extraField, 1, cde.extraFieldLength, p_in); } char* p_comment = 0; if(cde.commentLength) { p_comment = new char[cde.commentLength]; fread(p_comment, 1, cde.commentLength, p_in); } // merken, wo es nachher weitergeht unsigned int nextCDE = ftell(p_in); // Stimmt der Dateiname mit dem zu löschenden Dateinamen überein? if(!_stricmp(objectName.c_str(), p_filename)) { ecdOut.entriesOnThisDisk--; ecdOut.totalEntries--; ecdOut.centralDirectorySize -= sizeof(cde) + cde.filenameLength + cde.extraFieldLength + cde.commentLength; result = 1; delete[] p_filename; delete[] p_extraField; delete[] p_comment; } else { // Diese Datei soll kopiert werden. Zuerst lesen wir ihren lokalen Header. LocalFileHeader lfh; fseek(p_in, cde.localHeaderOffset, SEEK_SET); fread(&lfh, sizeof(lfh), 1, p_in); // Dateiname und Extrafeld überspringen fseek(p_in, lfh.filenameLength + lfh.extraFieldLength, SEEK_CUR); // Daten lesen char* p_fileData = new char[lfh.compressedSize]; fread(p_fileData, 1, lfh.compressedSize, p_in); // lokalen Header schreiben cdeOut.localHeaderOffset = ftell(p_out); fwrite(&lfh, 1, sizeof(lfh), p_out); fwrite(p_filename, 1, lfh.filenameLength, p_out); if(lfh.extraFieldLength) fwrite(p_extraField, 1, lfh.extraFieldLength, p_out); fwrite(p_fileData, 1, lfh.compressedSize, p_out); delete[] p_fileData; // Eintrag für das zentrale Verzeichnis merken cdOut.push_back(cdeOut); filenameOut.push_back(p_filename); extraFieldOut.push_back(p_extraField); commentOut.push_back(p_comment); } fseek(p_in, nextCDE, SEEK_SET); } // zentrales Verzeichnis schreiben ecdOut.centralDirectoryOffset = ftell(p_out); for(unsigned int i = 0; i < cdOut.size(); i++) { CentralDirectoryEntry& cde = cdOut[i]; fwrite(&cde, 1, sizeof(cde), p_out); char* p_filename = filenameOut[i]; char* p_extraField = extraFieldOut[i]; char* p_comment = commentOut[i]; fwrite(p_filename, 1, cde.filenameLength, p_out); if(cde.extraFieldLength) fwrite(p_extraField, 1, cde.extraFieldLength, p_out); if(cde.commentLength) fwrite(p_comment, 1, cde.commentLength, p_out); delete[] p_filename; delete[] p_extraField; delete[] p_comment; } // Ende schreiben fwrite(&ecdOut, 1, sizeof(ecdOut), p_out); if(ecdOut.globalCommentLength) fwrite(p_globalComment, 1, ecdOut.globalCommentLength, p_out); delete[] p_globalComment; fclose(p_in); fclose(p_out); // altes Archiv löschen remove(archiveFilename.c_str()); if(ecdOut.totalEntries) { // neue Datei umbenennen rename((archiveFilename + "_").c_str(), archiveFilename.c_str()); } else { // neue Datei löschen remove((archiveFilename + "_").c_str()); result = -1; } return result; } #pragma pack(pop) |
C-/C++-Quelltext |
|
1 2 |
if(password.empty()) result = unzOpenCurrentFilePassword(archive, password.c_str()); else result = unzOpenCurrentFile(archive); |
Administrator
Administrator
Zitat von »"David Scherfgen"«
Du solltest neben unzip.c auch die anderen .c-Dateien aus dem minizip-Verzeichnis zum Projekt hinzufügen – außer minizip.c und miniunz.c, denn dabei handelt es sich um eigenständige Programme (zum Packen und Entpacken per Kommandozeile).
Administrator
Werbeanzeige