1. 程式人生 > >zipfile.BadZipfile: File name in directory "AndroidManifest.xml" and header "META-INF/MANIFEST.MF" d

zipfile.BadZipfile: File name in directory "AndroidManifest.xml" and header "META-INF/MANIFEST.MF" d

問題

python 使用zipfile庫來解壓apk壓縮檔案的時候,出現了報錯zipfile.BadZipfile: File name in directory "AndroidManifest.xml" and header "META-INF/MANIFEST.MF" differ.

剖析問題

根據異常日誌,

File “c:\Python27\lib\zipfile.py”, line 1028, in extract
return self._extract_member(member, path, pwd)
File “c:\Python27\lib\zipfile.py

”, line 1082, in _extract_member
with self.open(member, pwd=pwd) as source,
File “c:\Python27\lib\zipfile.py”, line 980, in open
zinfo.orig_filename, fname)
zipfile.BadZipfile: File name in directory “AndroidManifest.xml” and header “META-INF/MANIFEST.MF” differ.

丟擲異常的地方是:c:\Python27\lib\zipfile.py", line 980

,我們去程式碼處看看,到底幹了什麼?
從下面程式碼可以看出,這是個開啟壓縮檔案的函式,找準關鍵點fname != zinfo.orig_filename這兩個變數是關鍵,fname = zef_file.read(fheader[_FH_FILENAME_LENGTH]) 這個語句大致可以從命名看出是讀取檔案頭一定偏移處的內容,大概。zinfo.orig_filename這個是zipinfo物件的檔名,也就是我想提取出來的檔名稱,是zipinfo物件的一個屬性,也就是可能是檔案頭一定偏移處的內容和要提取的檔名對比,出現的不同

    def open(self, name, mode="r", pwd=None):
        """Return file-like object for 'name'."""
        if mode not in ("r", "U", "rU"):
            raise RuntimeError, 'open() requires mode "r", "U", or "rU"'
        if not self.fp:
            raise RuntimeError, \
                  "Attempt to read ZIP archive that was already closed"

        # Only open a new file for instances where we were not
        # given a file object in the constructor
        if self._filePassed:
            zef_file = self.fp
            should_close = False
        else:
            zef_file = open(self.filename, 'rb')
            should_close = True

        try:
            # Make sure we have an info object
            if isinstance(name, ZipInfo):
                # 'name' is already an info object
                zinfo = name
            else:
                # Get info object for name
                zinfo = self.getinfo(name)

            zef_file.seek(zinfo.header_offset, 0)

            # Skip the file header:
            fheader = zef_file.read(sizeFileHeader)
            if len(fheader) != sizeFileHeader:
                raise BadZipfile("Truncated file header")
            fheader = struct.unpack(structFileHeader, fheader)
            if fheader[_FH_SIGNATURE] != stringFileHeader:
                raise BadZipfile("Bad magic number for file header")

            fname = zef_file.read(fheader[_FH_FILENAME_LENGTH])
            if fheader[_FH_EXTRA_FIELD_LENGTH]:
                zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH])

            if fname != zinfo.orig_filename:
                raise BadZipfile, \
                        'File name in directory "%s" and header "%s" differ.' % (
                            zinfo.orig_filename, fname)

為了確認上面的分析的正確性,我們看看這個zip包的檔案結構
出現報錯的zip檔案結構
下面是一個可以使用zipfile提取檔案的壓縮包的檔案結構,我們對比一下,可以看出確實是檔案頭這塊除了問題。然後嘗試提取這個有出現問題zip包的其他檔案,是可以提取的

解決方法

上面這個問題的解決方法我自己沒有找到辦法,如果有大佬知道,歡迎評論。
暫時使用別的方法來替代這個zipfile壓縮庫,我選擇的是使用java 寫一個jar解壓工具,使用流的方式來解壓縮

簡書:程式碼位置