며칠 전에 서버에서 작업을 진행하다가 용량 문제 때문에 잘 안 쓰는 대량의 파일들을 zip으로 압축해둔적이 있습니다. 문제는 zip 포맷의 한계로 4GB 이상의 파일을 다룰수가 없다는 문제가 있는걸 모르고 그냥 압축을 진행한 뒤 생성된 압축파일을 검증하지도 않고 그냥 원본 파일들을 다 지워버렸던 거죠. 뒤늦게 알아차리고 zip파일 압축을 해제하려고 했으나 손상된 파일이라며 압축 해제를 계속 실패했습니다...
Archive: archive.zip
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
note: archive.zip may be a plain executable, not an archive
unzip: cannot find zipfile directory in one of archive.zip or
archive.zip.zip, and cannot find archive.zip.ZIP, period.
(아 안돼...)
여러 압축 유틸을 받아서 열어보았지만, 복구되는 파일은 4개에 불과했습니다. (전체 압축한게 1만개가 넘었는데...) 도저히 자료를 그대로 날릴수가 없어서 ZIP 파일 포맷 명세를 확인해보았습니다.
https://en.wikipedia.org/wiki/Zip_(file_format)
정말 다행인게 ZIP 포맷은 오픈소스로 명세가 다 공개되어있고, 또한 압축이 파일 단위로 진행되기에 일부 손상된 파일이 있어도 나머지 파일들은 멀쩡하게 복구할 수 있다는 거였습니다.
ZIP파일의 구조를 간략하게 설명하자면, 먼저 N개의 File Entry가 차례대로 나열되고, 마지막에 Central Directory 정보가 덧붙습니다. 사실 실제 압축된 파일의 정보들은 File Entry에 들어가고, Central Directory 정보에는 기타 메타데이터 및 빠른 파일 색인을 위한 정보들이 있는것이라서 이 부분은 없어도 파일을 복구하는데에는 문제가 없습니다.
File Entry의 구조는 다음과 같습니다.
Offset | Bytes | Description |
---|---|---|
0 | 4 | 파일헤더 시그니처 ('PK\x03\x04'의 값) |
4 | 2 | 버전 |
6 | 2 | 범용 비트 플래그 |
8 | 2 | 압축 방법 |
10 | 2 | 마지막 수정 시간 |
12 | 2 | 마지막 수정 날짜 |
14 | 4 | CRC-32 |
18 | 4 | 압축된 크기 |
22 | 4 | 압축되기 전 크기 (r) |
26 | 2 | 파일 이름 길이 (n) (바이트 단위) |
28 | 2 | 기타 필드 길이 (m) (바이트 단위) |
30 | n | 파일 이름 |
30+n | m | 기타 필드 |
30+n+m | r | 압축된 데이터 (총 r바이트 길이) |
이 부분이 계속 반복되면서 총 N개의 파일을 표현하는 것이죠. 만약 정상적인 파일이라면 하나의 File Entry를 다 읽은 다음에는 바로 다음 File Entry가 등장해야합니다. 이건 파일 헤더 시그니처 값이 'PK\x03\x04'가 나오는지를 통해서 확인할 수 있습니다.
그럼 제 파일은 왜 압축 해제 유틸에서 제대로 열리지 않았을까요? 이는 앞의 4개까지는 File Entry가 제대로 나왔는데, 그 다음부터는 잘못된 값들이 덮어씌워져 파일 헤더가 제대로 나타나지 않았기 때문입니다.
PK.. ~~~~~~ PK.. ~~~~~~~~~~~ PK.. ~~~ PK.. ~~~~~
원래는 위와 같은 모양으로 데이터가 나와야하는데 중간에 잘못된 값이 덮어씌워져서
PK.. ~~~~~~ PK.. ~~~~~~~~~ABCBASBD~~ PK.. ~~~~~
PK..가 등장할것으로 예상되는 지점에 다른 값이 섞여버려 있더라구요. 이렇게 되면 두번째 파일과 세번째 파일은 사실 값이 깨졌기 때문에 복구할수가 없습니다. 그러나 네 번째 파일부터는 또 제대로 PK..라고 시그니처가 등장하기 때문에 이 지점부터는 또 복구가 가능합니다. 따라서 중간에 예상치 않은 잘못된 값이 들어왔을 경우 다음 헤더 시그니처인 PK\x03\x04의 위치를 찾아 점프하는 식으로 살릴 수 있는 모든 File Entry를 발견할 수 있습니다.
그래서 급하게 코딩을 했습니다.
코드를 실행할때 손상된 zip파일의 경로를 argument로 넘겨주면, 그 중에서 복구 가능한 File Entry만 추출하여 restored.zip으로 저장합니다. 이렇게 되면 restored.zip파일은 비록 Central Directory는 없지만 다른 압축 유틸에서 충분히 복구가 가능한 상태가 됩니다.
압축을 시도했던 원본 파일들이 약 1만개가 넘었는데, 이 방법을 통해 720개를 제외한 나머지 9천 여개의 파일들을 복구할 수 있었습니다. (십년 감수했지요) 혹시나 저와 같이 문제를 겪으시는 분들을 위해 코드를 공유하니 자유롭게 쓰시면 되겠습니다.
물론 제일 좋은건 손상된 zip파일을 만들지 않는 것이구요!
결론1: 파일을 지우기 전에 3번만 더 생각하자.
결론2: ZIP파일은 오래된 포맷이라 4GB 이상의 파일을 지원하지 않는다!
[c++] 빠른 log sigmoid 계산 (0) | 2019.01.02 |
---|---|
[Python] 임의의 웹 페이지에서 텍스트를 추출하기 (1) | 2018.11.04 |
[Python] 호환용 한자를 통합 한자로 변환하기 (2) | 2018.10.28 |
[Python3] 손상된 ZIP 압축 파일 복구하기 (26) | 2018.06.24 |
SIMD를 이용한 깁스 샘플링 연산 최적화(SSE2, AVX) (0) | 2018.05.06 |
동시출현빈도 제대로 계산하기! (9) | 2018.03.04 |
영어 동사 원형 복원기(English Verb Lemmatizer) (0) | 2017.09.26 |
댓글 영역
w = open('restored.' + 'my.zip', 'wb')
with open('my.zip', 'rb') as f:
처럼요
이 코드를 어디다가 써야 실행이되나오 ㅠㅠㅠㅠ부탁드립니다 도와주세요...ㅠㅠㅠㅠㅠ
1.python과 pycharm community edition는 깔았는데 어떻게 코드를 넣고 그걸 실행하는지잘모르겠습니다...
2.그리고 파이썬 폴더와 같은 폴더에 두라고하셨는데
파이썬폴더 위치가 어디있나요??
그리고 해당 폴더가 열려있는 탐색기 창주소줄에
python zipfixer.py <손상된zip파일이름>
라고 입력하시면 해당 코드가 실행됩니다.
글에서 자세히 알려주셨던 전문적인 방법이 아니라 이렇게 쉽게된다구요..?
해봤는데 cmd창 같은거뜨고 아무일이없네요...ㅠㅠㅠㅠㅠ
동작자체를 안하는거같은데
음...최상위폴더여야되는건가..흐아
막 따로 코드 실행되서 나온 압축파일이 그 폴더에 저ㅏㅈㅇ되고 그러지
다른곳에 저장되거나 그러지않죠?
해당 탐색기 창 주소줄에 cmd를 입력하셔서 cmd창을 켜시고, 거기서
python zipfixer.py <손상된zip파일이름>
라고 입력해보세요. 어떤 에러메세지가 나오는지 보실수 있을거에요
혹시 카카오톡 오픈채팅으로 가능하실까요??
만약 압축파일이 복구된다면 작은 사례라도 하겠습니다 ㅠㅠㅠㅠ
그와중에 님이 올려주신 자료에서 빛을 본 상태입니다. ㅠㅜㅠㅜ
혹시 파이선이 아니라 visual studio로 사용할 수 있는 소스는 없나요?
혹은 위 소스를 visual studio로 사용할 수 있나요?
문의 드립니다. 혹시 추가적인 문의 사항은 메일로 소통할 수 있을까요?
도움이 될 수 있는 상황이라면 bab2min@gmail.com 으로 연락주시면 도와드리도록 하겠습니다.
파이썬 초보자 분들이 사용하기 쉽게 변형해 보았습니다..