Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从zip文件中提取文件并保留修改日期?_Python_Zip_Extraction - Fatal编程技术网

Python 从zip文件中提取文件并保留修改日期?

Python 从zip文件中提取文件并保留修改日期?,python,zip,extraction,Python,Zip,Extraction,我尝试使用Python2.7.1(在Windows上,仅供参考)从zip文件中提取文件,每次尝试都会显示修改日期=提取时间的提取文件(这是不正确的) 我还尝试使用.extractall方法,得到了相同的结果 import os,zipfile outDirectory = 'C:\\_TEMP\\' inFile = 'test.zip' zFile = zipfile.ZipFile(os.path.join(outDirectory,inFile)) zFile.extrac

我尝试使用Python2.7.1(在Windows上,仅供参考)从zip文件中提取文件,每次尝试都会显示修改日期=提取时间的提取文件(这是不正确的)

我还尝试使用.extractall方法,得到了相同的结果

import os,zipfile
outDirectory = 'C:\\_TEMP\\'
inFile = 'test.zip'
zFile = zipfile.ZipFile(os.path.join(outDirectory,inFile))        
zFile.extractall(outDirectory)
谁能告诉我我做错了什么


我认为这是可能的,而无需对修改后的时间进行后期更正。

好吧,这确实需要一些后期处理,但也没那么糟糕:

import os
import zipfile
import time

outDirectory = 'C:\\TEMP\\'
inFile = 'test.zip'
fh = open(os.path.join(outDirectory,inFile),'rb') 
z = zipfile.ZipFile(fh)

for f in z.infolist():
    name, date_time = f.filename, f.date_time
    name = os.path.join(outDirectory, name)
    with open(name, 'wb') as outFile:
        outFile.write(z.open(f).read())
    date_time = time.mktime(date_time + (0, 0, -1))
    os.utime(name, (date_time, date_time))

好吧,也许有那么糟糕。

根据Ethan Fuman的回答,我开发了这个版本(使用Python 2.6.6),它更为贴切:

zf = ZipFile('archive.zip', 'r')
for zi in zf.infolist():
    zf.extract(zi)
    date_time = time.mktime(zi.date_time + (0, 0, -1))
    os.utime(zi.filename, (date_time, date_time))
zf.close()

这将提取到当前工作目录,并使用ZipFile.extract()方法来写入数据,而不是创建文件本身。

根据Ber的回答,我开发了这个版本(使用Python 2.7.11),它还考虑了目录修改日期

from os import path, utime
from sys import exit
from time import mktime
from zipfile import ZipFile

def unzip(zipfile, outDirectory):
    dirs = {}

    with ZipFile(zipfile, 'r') as z:
        for f in z.infolist():
            name, date_time = f.filename, f.date_time
            name = path.join(outDirectory, name)
            z.extract(f, outDirectory)

            # still need to adjust the dt o/w item will have the current dt
            date_time = mktime(f.date_time + (0, 0, -1))

            if (path.isdir(name)):
                # changes to dir dt will have no effect right now since files are
                # being created inside of it; hold the dt and apply it later
                dirs[name] = date_time
            else:
                utime(name, (date_time, date_time))

    # done creating files, now update dir dt
    for name in dirs:
       date_time = dirs[name]
       utime(name, (date_time, date_time))

if __name__ == "__main__":

    unzip('archive.zip', 'out')

    exit(0)

由于在目录中创建提取的文件时会修改目录,因此在提取完成之前,似乎没有必要使用
os.utime
设置日期,因此此版本会将目录名及其时间戳缓存到最后。

基于Jia103的回答,我开发了一个函数(使用Python2.7.14),它在提取所有内容后保留目录和文件日期。这将隔离函数中的任何丑陋之处,您还可以使用zipfile.zipfile.extractAll()或任何您想要的zip提取方法:

import time
import zipfile
import os

# Restores the timestamps of zipfile contents.
def RestoreTimestampsOfZipContents(zipname, extract_dir):
    for f in zipfile.ZipFile(zipname, 'r').infolist():
        # path to this extracted f-item
        fullpath = os.path.join(extract_dir, f.filename)
        # still need to adjust the dt o/w item will have the current dt
        date_time = time.mktime(f.date_time + (0, 0, -1))
        # update dt
        os.utime(fullpath, (date_time, date_time))
要保留日期,只需在提取完成后调用此函数

下面是一个示例,来自我编写到zip/unzip游戏保存目录的脚本:

        z = zipfile.ZipFile(zipname, 'r')
        print 'I have opened zipfile %s, ready to extract into %s' \
                % (zipname, gamedir)
        try: os.makedirs(gamedir)
        except: pass    # Most of the time dir already exists
        z.extractall(gamedir)
        RestoreTimestampsOfZipContents(zipname, gamedir)  #<--  USED
        print '%s zip extract done' % GameName[game]
z=zipfile.zipfile(zipname,'r')
打印“我已打开zipfile%s,准备提取到%s”\
%(zipname,gamedir)
try:os.makedirs(gamedir)
除了:pass#大部分时间dir已经存在
z、 提取全部(gamedir)

RestoreTimestampsOfZipContents(zipname,gamedir)#你会很失望的……即使对于Python 3.X来说,这似乎仍然是一个问题。谢谢。为了澄清,维护文件提取的mod date是Python zipfile实现的一个限制,还是这一标准功能在所有zip库中都存在?自回复以来已经5年了,它仍然在Python 3.6下工作。它仍然像您编写它的那天一样难看,但是它可以工作。Python 3.6仍然需要这样做吗?查看源代码,我看不到与日期/时间信息相关的任何更改…您能解释一下为什么要在日期/时间中添加(0,0,-1)吗?当前值是秒关闭吗?@RvdK:the
(0,0,-1)
被添加,因为它需要一个9元素的
元组。
-1
表示
DST
标志未知。我正在尝试使用此代码,但所有文件都保存到我的根目录中。我应该在哪里定义保存文件的路径?@newwebdev22代码提取到当前目录。您可以更改它,也可以向extract()方法添加一个path参数,如文档中所述:此外,您可能不会检查ZIP存档中的绝对路径。
        z = zipfile.ZipFile(zipname, 'r')
        print 'I have opened zipfile %s, ready to extract into %s' \
                % (zipname, gamedir)
        try: os.makedirs(gamedir)
        except: pass    # Most of the time dir already exists
        z.extractall(gamedir)
        RestoreTimestampsOfZipContents(zipname, gamedir)  #<--  USED
        print '%s zip extract done' % GameName[game]