2013-11-20 21 views
12

7z sıkıştırılmış bir csv (text) dosyasından satır satır satır okumak istiyorum (Python 2.7'de). Tüm (büyük) dosyaları sıkıştırmak istemiyorum ama satırları akıtmak.7z ile sıkıştırılmış bir metin dosyasından nasıl okunur?

pylzma.decompressobj()'u denedim başarısız. Veri hatası alıyorum. Bu kod henüz satır satır okumak unutmayın:

input_filename = r"testing.csv.7z" 
with open(input_filename, 'rb') as infile: 
    obj = pylzma.decompressobj() 
    o = open('decompressed.raw', 'wb') 
    obj = pylzma.decompressobj() 
    while True: 
     tmp = infile.read(1) 
     if not tmp: break 
     o.write(obj.decompress(tmp)) 
    o.close() 

Çıktı: Python 3.3+ kullanarak olsaydı

o.write(obj.decompress(tmp)) 
ValueError: data error during decompression 
+2

Neden kodu ve bir örnek dosyayı yayınlamayın? –

+0

.7z dosyası, birden fazla dosya içerebilen kapsayıcılardır (arşivler), yani okumak istediğiniz 'test.7z 'içindeki dosya adı nedir? – martineau

+0

@martineau, testing.csv – Yariv

cevap

7

Bu satırları yineleme sağlayacaktır. Başka bir soruya answer'da bulduğum bazı kodlardan kısmen türetilmiş.

Bildiğim kadarıyla, zaman içinde bu noktada py7zlib arşiv üyeleri bayt veya bir akışı olarak okunmasına izin verecek bir API sağlamaz söyleyebilirim karakterlerin-onun ArchiveFile sınıf yalnızca basıncı azaltan read() fonksiyonu sağlar ve sıkıştırılmamış tüm verileri bir kerede üye olan bir kerede verir. Bunu yaptığınızda, yapabileceğiniz en iyi şey, bir arabellek olarak yinelemeli olarak bayt veya satır döndürmektir. Aşağıdaki, ancak sorun arşiv üyesi dosyanın kendisi çok ise çok yardımcı değil.

Python 2.7 ve 3.x'te çalışmak için aşağıdaki kodu değiştirdim.

import io 
import os 
import py7zlib 

class SevenZFileError(py7zlib.ArchiveError): 
    pass 

class SevenZFile(object): 
    @classmethod 
    def is_7zfile(cls, filepath): 
     """ Determine if filepath points to a valid 7z archive. """ 
     is7z = False 
     fp = None 
     try: 
      fp = open(filepath, 'rb') 
      archive = py7zlib.Archive7z(fp) 
      _ = len(archive.getnames()) 
      is7z = True 
     finally: 
      if fp: fp.close() 
     return is7z 

    def __init__(self, filepath): 
     fp = open(filepath, 'rb') 
     self.filepath = filepath 
     self.archive = py7zlib.Archive7z(fp) 

    def __contains__(self, name): 
     return name in self.archive.getnames() 

    def readlines(self, name): 
     """ Iterator of lines from an archive member. """ 
     if name not in self: 
      raise SevenZFileError('archive member %r not found in %r' % 
            (name, self.filepath)) 

     for line in io.StringIO(self.archive.getmember(name).read().decode()): 
      yield line 

Örnek kullanım: Biz hata üretebilir ve nasıl yardımcı olabiliriz görebilirsiniz

import csv 

if SevenZFile.is_7zfile('testing.csv.7z'): 
    sevenZfile = SevenZFile('testing.csv.7z') 

    if 'testing.csv' not in sevenZfile: 
     print('testing.csv is not a member of testing.csv.7z') 
    else: 
     reader = csv.reader(sevenZfile.readlines('testing.csv')) 
     for row in reader: 
      print(', '.join(row)) 
2

, sen olduğunu lzma modülünü kullanarak bunu yapmak mümkün olabilir Bu sürümdeki standart kitaplığa eklendi.

bakınız: lzmaExamples

+2

Soru 'python-2.7' ile etiketlenmiştir, bu yüzden * burada * Python 3 olduğunu varsayabiliriz. –

+0

Ayrıca, python 3,3 (doc bağlantısından) 'dan bahsetmeli ve sadece 3 değil. –

+1

@MartijnPieters yorum yaptığımda bu etiketi kullanmamıştı. – blakev

İlgili konular