0

コンピューターが私をからかっている、私はそれを知っています!

Pythonでzipフォルダーを作成しています。個々のファイルはメモリ内で生成され、全体が圧縮されてファイルに保存されます。zip には 9 個のファイルを追加できます。zip には 11 個のファイルを追加できます。しかし、10、いや、10 ファイルではありません。zip ファイルはコンピューターに保存されていますが、開くことができません。Windows は、圧縮された zip フォルダーが無効であると言います。

別のスタックオーバーフローの質問から取得した以下のコードを使用します。10 個のファイルを追加し、zip フォルダーを保存します。フォルダをクリックしても解凍できません。しかし、appends() の 1 つを削除すれば問題ありません。または、別の追加を追加すると機能します!

ここで何が欠けていますか?毎回これを機能させるにはどうすればよいですか?

imz = InMemoryZip() 
imz.append("1a.txt", "a").append("2a.txt", "a").append("3a.txt", "a").append("4a.txt", "a").append("5a.txt", "a").append("6a.txt", "a").append("7a.txt", "a").append("8a.txt", "a").append("9a.txt", "a").append("10a.txt", "a")
imz.writetofile("C:/path/test.zip") 


import zipfile
import StringIO
class InMemoryZip(object):
    def __init__(self):
        # Create the in-memory file-like object
        self.in_memory_zip = StringIO.StringIO()

    def append(self, filename_in_zip, file_contents):
        '''Appends a file with name filename_in_zip and contents of 
        file_contents to the in-memory zip.'''
        # Get a handle to the in-memory zip in append mode
        zf = zipfile.ZipFile(self.in_memory_zip, "a", zipfile.ZIP_DEFLATED, False)

        # Write the file to the in-memory zip
        zf.writestr(filename_in_zip, file_contents)

        # Mark the files as having been created on Windows so that
        # Unix permissions are not inferred as 0000
        for zfile in zf.filelist:
            zfile.create_system = 0        

        return self

    def read(self):
        '''Returns a string with the contents of the in-memory zip.'''
        self.in_memory_zip.seek(0)
        return self.in_memory_zip.read()

    def writetofile(self, filename):
        '''Writes the in-memory zip to a file.'''
        f = file(filename, "w")
        f.write(self.read())
        f.close()
4

1 に答える 1

1

ファイル システムに保存するファイルを作成するときは、「wb」モードを使用する必要があります。これにより、ファイルがバイナリで書き込まれます。

それ以外の場合、zip ファイル内で改行 (\n) 文字が検出されると、python はそれを Windows の行末 (\r\n) に一致するように置き換えます。10 個のファイルが問題になる理由は、たまたま 10 個が \n のコードであるためです。

したがって、書き込み関数は次のようになります。

def writetofile(self, filename):
    '''Writes the in-memory zip to a file.'''
    f = file(filename, 'wb')
    f.write(self.read())
    f.close()

これで問題が解決し、例のファイルで機能するはずです。ただし、あなたのケースでは、上記のコメントの一部を含む次のコードのように、zip ファイルをファイル システムに直接書き込む方が簡単な場合があります。

import StringIO
import zipfile

class ZipCreator:
    buffer = None

    def __init__(self, fileName=None):
        if fileName:
            self.zipFile = zipfile.ZipFile(fileName, 'w', zipfile.ZIP_DEFLATED, False)
            return

        self.buffer = StringIO.StringIO()
        self.zipFile = zipfile.ZipFile(self.buffer, 'w', zipfile.ZIP_DEFLATED, False)

    def addToZipFromFileSystem(self, filePath, filenameInZip):
        self.zipFile.write(filePath, filenameInZip)

    def addToZipFromMemory(self, filenameInZip, fileContents):
        self.zipFile.writestr(filenameInZip, fileContents)

        for zipFile in self.zipFile.filelist:
            zipFile.create_system = 0

    def write(self, fileName):            
        if not self.buffer:  # If the buffer was not initialized the file is written by the ZipFile
            self.zipFile.close()
            return

        f = file(fileName, 'wb')
        f.write(self.buffer.getvalue())
        f.close()

# Use File Handle
zipCreator = ZipCreator('C:/path/test.zip')

# Use Memory Buffer
# zipCreator = ZipCreator()

for i in range(1, 10):
    zipCreator.addToZipFromMemory('test/%sa.txt' % i, 'a')

zipCreator.write('C:/path/test.zip')

理想的には、メモリ内の zip と最初からファイル システムに関連付けられている zip に別々のクラスを使用するでしょう。また、再作成が困難で、まだ追跡しようとしているフォルダーが追加されたときに、メモリ内の zip にいくつかの問題があるようです。

于 2013-09-05T22:46:43.907 に答える