首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >读取tar文件内容而不解压,在python脚本中

读取tar文件内容而不解压,在python脚本中
EN

Stack Overflow用户
提问于 2010-01-07 13:58:09
回答 4查看 78K关注 0票数 89

我有一个tar文件,里面有许多文件。我需要写一个python脚本,它将读取文件的内容,并给出总字符数,包括字母总数,空格,换行符,一切,而不是解压tar文件。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-01-07 14:17:30

您可以使用getmembers()

代码语言:javascript
复制
>>> import  tarfile
>>> tar = tarfile.open("test.tar")
>>> tar.getmembers()

之后,您可以使用extractfile()将成员提取为文件对象。这只是一个例子

代码语言:javascript
复制
import tarfile,os
import sys
os.chdir("/tmp/foo")
tar = tarfile.open("test.tar")
for member in tar.getmembers():
    f=tar.extractfile(member)
    content=f.read()
    print "%s has %d newlines" %(member, content.count("\n"))
    print "%s has %d spaces" % (member,content.count(" "))
    print "%s has %d characters" % (member, len(content))
    sys.exit()
tar.close()

对于上面示例中的文件对象f,您可以使用read()readlines()等。

票数 134
EN

Stack Overflow用户

发布于 2010-01-07 14:01:44

您需要使用tarfile模块。具体地说,您使用类TarFile的一个实例来访问该文件,然后使用TarFile.getnames()访问名称

代码语言:javascript
复制
 |  getnames(self)
 |      Return the members of the archive as a list of their names. It has
 |      the same order as the list returned by getmembers().

如果您想要读取内容,则使用此方法

代码语言:javascript
复制
 |  extractfile(self, member)
 |      Extract a member from the archive as a file object. `member' may be
 |      a filename or a TarInfo object. If `member' is a regular file, a
 |      file-like object is returned. If `member' is a link, a file-like
 |      object is constructed from the link's target. If `member' is none of
 |      the above, None is returned.
 |      The file-like object is read-only and provides the following
 |      methods: read(), readline(), readlines(), seek() and tell()
票数 13
EN

Stack Overflow用户

发布于 2014-04-26 15:35:13

之前,这篇文章展示了一个“dict(zip(())”将成员名称和成员列表放在一起的例子,这很愚蠢,并导致过度读取存档,为了实现同样的目的,我们可以使用字典理解:

代码语言:javascript
复制
index = {i.name: i for i in my_tarfile.getmembers()}

有关如何使用tarfile的详细信息

提取tarfile成员

代码语言:javascript
复制
#!/usr/bin/env python3
import tarfile

my_tarfile = tarfile.open('/path/to/mytarfile.tar')

print(my_tarfile.extractfile('./path/to/file.png').read())

为tar文件编制索引

代码语言:javascript
复制
#!/usr/bin/env python3
import tarfile
import pprint

my_tarfile = tarfile.open('/path/to/mytarfile.tar')

index = my_tarfile.getnames()  # a list of strings, each members name
# or
# index = {i.name: i for i in my_tarfile.getmembers()}

pprint.pprint(index)

索引、读取、动态附加tar文件

代码语言:javascript
复制
#!/usr/bin/env python3

import tarfile
import base64
import textwrap
import random

# note, indexing a tar file requires reading it completely once
# if we want to do anything after indexing it, it must be a file
# that can be seeked (not a stream), so here we open a file we
# can seek
my_tarfile = tarfile.open('/path/to/mytar.tar')


# tarfile.getmembers is similar to os.stat kind of, it will
# give you the member names (i.name) as well as TarInfo attributes:
#
# chksum,devmajor,devminor,gid,gname,linkname,linkpath,
# mode,mtime,name,offset,offset_data,path,pax_headers,
# size,sparse,tarfile,type,uid,uname
#
# here we use a dictionary comprehension to index all TarInfo
# members by the member name
index = {i.name: i for i in my_tarfile.getmembers()}

print(index.keys())

# pick your member
# note: if you can pick your member before indexing the tar file,
# you don't need to index it to read that file, you can directly
# my_tarfile.extractfile(name)
# or my_tarfile.getmember(name)

# pick your filename from the index dynamically
my_file_name = random.choice(index.keys())

my_file_tarinfo = index[my_file_name]
my_file_size = my_file_tarinfo.size
my_file_buf = my_tarfile.extractfile( 
    my_file_name
    # or my_file_tarinfo
)

print('file_name: {}'.format(my_file_name))
print('file_size: {}'.format(my_file_size))
print('----- BEGIN FILE BASE64 -----'
print(
    textwrap.fill(
        base64.b64encode(
            my_file_buf.read()
        ).decode(),
        72
    )
)
print('----- END FILE BASE64 -----'

包含重复成员的tarfile

在我们有一个奇怪创建的tar的情况下,在这个例子中,通过将同一文件的多个版本附加到同一个tar归档中,我们可以仔细地使用它,我已经注释了哪些成员包含什么文本,假设我们想要第四个(索引3)成员,"capturetheflag\n“

代码语言:javascript
复制
tar -tf mybadtar.tar 
mymember.txt  # "version 1\n"
mymember.txt  # "version 1\n"
mymember.txt  # "version 2\n"
mymember.txt  # "capturetheflag\n"
mymember.txt  # "version 3\n"
代码语言:javascript
复制
#!/usr/bin/env python3

import tarfile
my_tarfile = tarfile.open('mybadtar.tar')

# >>> my_tarfile.getnames()
# ['mymember.txt', 'mymember.txt', 'mymember.txt', 'mymember.txt', 'mymember.txt']

# if we use extracfile on a name, we get the last entry, I'm not sure how python is smart enough to do this, it must read the entire tar file and buffer every valid member and return the last one

# >>> my_tarfile.extractfile('mymember.txt').read()
# b'version 3\n'

# >>> my_tarfile.extractfile(my_tarfile.getmembers()[3]).read()
# b'capturetheflag\n'

或者,我们可以遍历tar文件#!/usr/bin/env python3

代码语言:javascript
复制
import tarfile
my_tarfile = tarfile.open('mybadtar.tar')
# note, if we do anything to the tarfile object that will 
# cause a full read, the tarfile.next() method will return none,
# so call next in a loop as the first thing you do if you want to
# iterate

while True:
    my_member = my_tarfile.next()
    if not my_member:
        break
    print((my_member.offset, mytarfile.extractfile(my_member).read,))

# (0, b'version 1\n')
# (1024, b'version 1\n')
# (2048, b'version 2\n')
# (3072, b'capturetheflag\n')
# (4096, b'version 3\n')
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2018512

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档