java读取7z文件内容,如何从7z压缩的文本文件中读取?

I would like to read (in Python 2.7), line by line, from a csv (text) file, which is 7z compressed. I don't want to decompress the entire (large) file, but to stream the lines.

I tried pylzma.decompressobj() unsuccessfully. I get a data error. Note that this code doesn't yet read line by line:

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()

Output:

o.write(obj.decompress(tmp))

ValueError: data error during decompression

解决方案

This will allow you to iterate the lines. It's partially derived from some code I found in an answer to another question.

At this point in time (pylzma-0.5.0) the py7zlib module doesn't implement an API that would allow archive members to be read as a stream of bytes or characters — its ArchiveFile class only provides a read() function that decompresses and returns the uncompressed data in a member all at once. Given that, about the best that can be done is return bytes or lines iteratively via a Python generator using that as a buffer.

The following does the latter, but may not help if the problem is the archive member file itself is huge.

The code below should work in Python 3.x as well as 2.7.

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, newline=''):

r""" Iterator of lines from named archive member.

`newline` controls how line endings are handled.

It can be None, '', '\n', '\r', and '\r\n' and works the same way as it does

in StringIO. Note however that the default value is different and is to enable

universal newlines mode, but line endings are returned untranslated.

"""

archivefile = self.archive.getmember(name)

if not archivefile:

raise SevenZFileError('archive member %r not found in %r' %

(name, self.filepath))

# Decompress entire member and return its contents iteratively.

data = archivefile.read().decode()

for line in io.StringIO(data, newline=newline):

yield line

if __name__ == '__main__':

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))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值