From ac77b61cc488234d7b02ff85db5955254f741982 Mon Sep 17 00:00:00 2001 From: Juno Kim Date: Fri, 28 Aug 2026 10:05:16 +0900 Subject: [PATCH] add dir recursiv search --- ZipDefine.h | 2 +- main.cpp | 282 +++++++++++++++++++++++++++++++++------------------- 2 files changed, 179 insertions(+), 105 deletions(-) diff --git a/ZipDefine.h b/ZipDefine.h index 0131731..639df64 100644 --- a/ZipDefine.h +++ b/ZipDefine.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include diff --git a/main.cpp b/main.cpp index f09df6d..c11780e 100644 --- a/main.cpp +++ b/main.cpp @@ -1,16 +1,22 @@ -#include -#include +#include +#include #include -#include #include +#include +#include +#include + +#include +#include + #include "ZipDefine.h" #include "CRC.h" #define INPUT_FILE_NAME "MyZip.txt" #define OUTPUT_FILE_NAME "MyZip.zip" -bool ZipArchiver(); +bool FileReader(); int main() { @@ -18,7 +24,7 @@ int main() int iRet = 0; // Main Zip archive method - if(!ZipArchiver()) + if(!FileReader()) { iRet = -1; std::printf("[ ERROR ] Somthing went Wrong... \r\n"); @@ -30,8 +36,13 @@ int main() return iRet; } +bool searchDir() +{ -bool ZipArchiver() +} + + +bool FileReader() { LocalFileHeader LFHeader{}; CentralDirectory CentDir{}; @@ -47,116 +58,179 @@ bool ZipArchiver() } else { - // 파일 크기 계산 - // TODO : Buffering 으로 구현. 현재는 파일 통짜로 읽음. - fileIn.seekg(0, ios::end); // seekg(offset, 목표점) - streamsize fileInSize = fileIn.tellg(); - fileIn.seekg(0, ios::beg); // beg == begin + // path class obj 생성. + filesystem::path pathObj(INPUT_FILE_NAME); - // 메모리 할당 - vector fileInBuffer(fileInSize); - auto* pInBuffer = reinterpret_cast(fileInBuffer.data()); - - // Read - fileIn.read(pInBuffer, fileInSize); - // ZIP 포맷 채워넣기 - // TODO : 클래스화 대상 + // file valid check + if (!filesystem::exists(pathObj)) { - // Get CRC value - uint32_t myCRC = getCRC32(pInBuffer, fileInSize); - - // Put PK Signature - LFHeader.signature = PK_SIGNATURE_LF_HEADER; - CentDir.signature = PK_SIGNATURE_CENT_DIR; - EOCDR.signature = PK_SIGNATURE_EO_CDR; - - // TOOD : Temp Format 채우기. - CentDir.versionMadeBy = 0; // Temp - LFHeader.versionNeededToExtract = 0; // Temp - CentDir.versionNeededToExtract = 0; // Temp - LFHeader.generalBitFlag = 0; // Temp - CentDir.generalBitFlag = 0; // Temp - - // Put compressed method (uncompressed) - LFHeader.compressionMethod = METHOD_UNCOMPRESSED; - CentDir.compressionMethod = METHOD_UNCOMPRESSED; - - // lastMode[Time|Date] => Not Used. - - // Put CRC value - LFHeader.crc32 = myCRC; - CentDir.crc32 = myCRC; - - // Put File size - LFHeader.sizeOfUncompressed = (uint32_t)fileInSize; - CentDir.sizeOfUncompressed = (uint32_t)fileInSize; - LFHeader.sizeOfCompressed = LFHeader.sizeOfUncompressed; - CentDir.sizeOfCompressed = CentDir.sizeOfUncompressed; - - // Put File name length - uint16_t fileNameLeng = static_cast(strlen(INPUT_FILE_NAME)); - LFHeader.lengthOfFileName = fileNameLeng; - CentDir.lengthOfFileName = fileNameLeng; - - // Extra Field 는 사용하지 않음 - // LFHeader.lengthOfExtraField = NOT_USED; - // CentDir.lengthOfExtraField = NOT_USED; - - // TODO : CentDir Temp format 채우기. - CentDir.lengthOfFileComment = 0; - CentDir.diskNumStart = 0; // Temp - CentDir.attributeInternal = 0; // Temp - CentDir.attributeExternal = 0; // Temp - // CentDir.offsetLocalFileHeader -> 실제 파일 Write 중에 작성. - - // TODO : EOCDR Temp format 채우기. - EOCDR.diskNumber = 0; // Temp - EOCDR.diskNumber_CentralDirStart = 0; // Temp - EOCDR.numOfCentralDir = 1; - EOCDR.numOfEntries = 1; - EOCDR.sizeOfCentralDir = sizeof(CentDir) + CentDir.lengthOfFileName; - // EOCDR.offsetCentralDir -> 실제 파일 Write 중에 작성. - EOCDR.lengthOfCommentLength = 0; + string strErr = "File not found : " + pathObj.string(); + OutputDebugStringA(strErr.c_str()); + return false; } - - // Zip arhcive 파일 쓰기 + if (!filesystem::is_regular_file(pathObj)) { - ofstream fileOut(OUTPUT_FILE_NAME, ios::binary); - iRet = fileOut.is_open(); - if (!iRet) + string strErr = "File is not regular file : " + pathObj.string(); + OutputDebugStringA(strErr.c_str()); + + // directory recursive search + + if (filesystem::is_directory(pathObj)) { - printf("FileOut open failed"); + filesystem::directory_iterator itrDir(pathObj); + + while (itrDir != filesystem::end(itrDir)) + { + // get entry one by one + const filesystem::directory_entry& currentEntry = *itrDir; + + if (filesystem::is_directory(currentEntry)) + { + // TODO : 다시 위로 돌아가야 함 + 재귀적으로 돌아가면서 처리 + // Do Something... + } + else if(filesystem::is_regular_file(currentEntry)) + { + // TODO : 파일 Archiving logic + ZipArchiver(); + } + else + { + // 애초에 제 3의 Type 이 있나? + OutputDebugStringA("Wrong Type of File"); + } + + // step forward entry + itrDir++; + } } else { - // 1. Local File Header, file name (var), extra field (var) - CentDir.offsetLocalFileHeader = static_cast(fileOut.tellp()); - // TODO : sizeof 의 값이 스펙과 정확히 일치한다는 보장 필요 (현재는 compiler 에 종속적) - // : offsetof((LocalFileHeader, crc32) 으로 멤버별 static_assert 로 변경할 지 고민. - // : 아니면 필드 단위 직접쓰기로 struct 분해하기? - fileOut.write(reinterpret_cast(&LFHeader), sizeof(LFHeader)); - fileOut.write(INPUT_FILE_NAME, LFHeader.lengthOfFileName); - //fileOut.write(NOT_USED, LFHeader.LFHeader.lengthOfExtraField); + // 이런 경우가 있으려나? 일단 혹시 모르니까 + string strErr = "Something went Wrong..!!"; + OutputDebugStringA(strErr.c_str()); - // 2. File Data - fileOut.write(pInBuffer, fileInSize); - - // 3. CentralDirectory, file name (var) - EOCDR.offsetCentralDir = static_cast(fileOut.tellp()); - // TODO : sizeof 의 값이 스펙과 정확히 일치한다는 보장 필요 (현재는 compiler 에 종속적) - fileOut.write(reinterpret_cast(&CentDir), sizeof(CentDir)); - fileOut.write(INPUT_FILE_NAME, CentDir.lengthOfFileName); - - // 4. End of CentralDirectory Record - // TODO : sizeof 의 값이 스펙과 정확히 일치한다는 보장 필요 (현재는 compiler 에 종속적) - fileOut.write(reinterpret_cast(&EOCDR), sizeof(EOCDR)); - - fileOut.close(); + return false; } } + else + { + ZipArchiver(); + } + } - // Free - free(pInBuffer); + // TODO : 어떤 식으로 Return 할 건지 하나만 정하기 + return iRet; +} + +bool ZipArchiver() +{ + // 파일 크기 계산 + // TODO : Buffering 으로 구현. 현재는 파일 통짜로 읽음. + fileIn.seekg(0, ios::end); // seekg (offset, 목표점) + streamsize fileInSize = fileIn.tellg(); + fileIn.seekg(0, ios::beg); // beg == begin + + // 메모리 할당 + vector fileInBuffer(fileInSize); + auto* pInBuffer = reinterpret_cast(fileInBuffer.data()); + + // Read + fileIn.read(pInBuffer, fileInSize); + // ZIP 포맷 채워넣기 + // TODO : 클래스화 대상 + { + // Get CRC value + uint32_t myCRC = getCRC32(pInBuffer, fileInSize); + + // Put PK Signature + LFHeader.signature = PK_SIGNATURE_LF_HEADER; + CentDir.signature = PK_SIGNATURE_CENT_DIR; + EOCDR.signature = PK_SIGNATURE_EO_CDR; + + // TOOD : Temp Format 채우기. + CentDir.versionMadeBy = 0; // Temp + LFHeader.versionNeededToExtract = 0; // Temp + CentDir.versionNeededToExtract = 0; // Temp + LFHeader.generalBitFlag = 0; // Temp + CentDir.generalBitFlag = 0; // Temp + + // Put compressed method (uncompressed) + LFHeader.compressionMethod = METHOD_UNCOMPRESSED; + CentDir.compressionMethod = METHOD_UNCOMPRESSED; + + // lastMode[Time|Date] => Not Used. + + // Put CRC value + LFHeader.crc32 = myCRC; + CentDir.crc32 = myCRC; + + // Put File size + LFHeader.sizeOfUncompressed = (uint32_t)fileInSize; + CentDir.sizeOfUncompressed = (uint32_t)fileInSize; + LFHeader.sizeOfCompressed = LFHeader.sizeOfUncompressed; + CentDir.sizeOfCompressed = CentDir.sizeOfUncompressed; + + // Put File name length + uint16_t fileNameLeng = static_cast(strlen(INPUT_FILE_NAME)); + LFHeader.lengthOfFileName = fileNameLeng; + CentDir.lengthOfFileName = fileNameLeng; + + // Extra Field 는 사용하지 않음 + // LFHeader.lengthOfExtraField = NOT_USED; + // CentDir.lengthOfExtraField = NOT_USED; + + // TODO : CentDir Temp format 채우기. + CentDir.lengthOfFileComment = 0; + CentDir.diskNumStart = 0; // Temp + CentDir.attributeInternal = 0; // Temp + CentDir.attributeExternal = 0; // Temp + // CentDir.offsetLocalFileHeader -> 실제 파일 Write 중에 작성. + + // TODO : EOCDR Temp format 채우기. + EOCDR.diskNumber = 0; // Temp + EOCDR.diskNumber_CentralDirStart = 0; // Temp + EOCDR.numOfCentralDir = 1; + EOCDR.numOfEntries = 1; + EOCDR.sizeOfCentralDir = sizeof(CentDir) + CentDir.lengthOfFileName; + // EOCDR.offsetCentralDir -> 실제 파일 Write 중에 작성. + EOCDR.lengthOfCommentLength = 0; + } + + // Zip arhcive 파일 쓰기 + { + ofstream fileOut(OUTPUT_FILE_NAME, ios::binary); + iRet = fileOut.is_open(); + if (!iRet) + { + printf("FileOut open failed"); + } + else + { + // 1. Local File Header, file name (var), extra field (var) + CentDir.offsetLocalFileHeader = static_cast(fileOut.tellp()); + // TODO : sizeof 의 값이 스펙과 정확히 일치한다는 보장 필요 (현재는 compiler 에 종속적) + // : offsetof((LocalFileHeader, crc32) 으로 멤버별 static_assert 로 변경할 지 고민. + // : 아니면 필드 단위 직접쓰기로 struct 분해하기? + fileOut.write(reinterpret_cast(&LFHeader), sizeof(LFHeader)); + fileOut.write(INPUT_FILE_NAME, LFHeader.lengthOfFileName); + //fileOut.write(NOT_USED, LFHeader.LFHeader.lengthOfExtraField); + + // 2. File Data + fileOut.write(pInBuffer, fileInSize); + + // 3. CentralDirectory, file name (var) + EOCDR.offsetCentralDir = static_cast(fileOut.tellp()); + // TODO : sizeof 의 값이 스펙과 정확히 일치한다는 보장 필요 (현재는 compiler 에 종속적) + fileOut.write(reinterpret_cast(&CentDir), sizeof(CentDir)); + fileOut.write(INPUT_FILE_NAME, CentDir.lengthOfFileName); + + // 4. End of CentralDirectory Record + // TODO : sizeof 의 값이 스펙과 정확히 일치한다는 보장 필요 (현재는 compiler 에 종속적) + fileOut.write(reinterpret_cast(&EOCDR), sizeof(EOCDR)); + + fileOut.close(); + } } return iRet;