mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Make extracting single files from RAR archives more efficient
This commit is contained in:
parent
466fb8f4f6
commit
76c6434898
@ -217,7 +217,41 @@ def names(path):
|
||||
finally:
|
||||
_libunrar.RARCloseArchive(arc_data)
|
||||
|
||||
def extract_member(path, match=re.compile(r'\.(jpg|jpeg|gif|png)\s*$', re.I), name=None):
|
||||
def _extract_member(path, match, name):
|
||||
|
||||
def is_match(fname):
|
||||
return (name is not None and fname == name) or \
|
||||
(match is not None and match.search(fname) is not None)
|
||||
|
||||
open_archive_data = RAROpenArchiveDataEx(ArcName=path, OpenMode=RAR_OM_EXTRACT, CmtBuf=None)
|
||||
arc_data = _libunrar.RAROpenArchiveEx(byref(open_archive_data))
|
||||
try:
|
||||
if open_archive_data.OpenResult != 0:
|
||||
raise UnRARException(_interpret_open_error(open_archive_data.OpenResult, path))
|
||||
header_data = RARHeaderDataEx(CmtBuf=None)
|
||||
first = True
|
||||
while True:
|
||||
if _libunrar.RARReadHeaderEx(arc_data, byref(header_data)) != 0:
|
||||
raise UnRARException('%s has no files'%path if first
|
||||
else 'No match found in %s'%path)
|
||||
file_name = header_data.FileNameW
|
||||
if is_match(file_name):
|
||||
PFCode = _libunrar.RARProcessFileW(arc_data, RAR_EXTRACT, None, None)
|
||||
if PFCode != 0:
|
||||
raise UnRARException(_interpret_process_file_error(PFCode))
|
||||
abspath = os.path.abspath(*file_name.split('/'))
|
||||
return abspath
|
||||
else:
|
||||
PFCode = _libunrar.RARProcessFileW(arc_data, RAR_SKIP, None, None)
|
||||
if PFCode != 0:
|
||||
raise UnRARException(_interpret_process_file_error(PFCode))
|
||||
first = False
|
||||
|
||||
finally:
|
||||
_libunrar.RARCloseArchive(arc_data)
|
||||
|
||||
def extract_member(path, match=re.compile(r'\.(jpg|jpeg|gif|png)\s*$', re.I),
|
||||
name=None, as_file=False):
|
||||
if hasattr(path, 'read'):
|
||||
data = path.read()
|
||||
f = NamedTemporaryFile(suffix='.rar')
|
||||
@ -225,34 +259,13 @@ def extract_member(path, match=re.compile(r'\.(jpg|jpeg|gif|png)\s*$', re.I), na
|
||||
f.flush()
|
||||
path = f.name
|
||||
|
||||
def is_match(fname):
|
||||
return (name is not None and fname == name) or \
|
||||
(match is not None and match.search(fname))
|
||||
|
||||
with TemporaryDirectory('_libunrar') as dir:
|
||||
with CurrentDir(dir):
|
||||
open_archive_data = RAROpenArchiveDataEx(ArcName=path, OpenMode=RAR_OM_EXTRACT, CmtBuf=None)
|
||||
arc_data = _libunrar.RAROpenArchiveEx(byref(open_archive_data))
|
||||
try:
|
||||
if open_archive_data.OpenResult != 0:
|
||||
raise UnRARException(_interpret_open_error(open_archive_data.OpenResult, path))
|
||||
header_data = RARHeaderDataEx(CmtBuf=None)
|
||||
while True:
|
||||
if _libunrar.RARReadHeaderEx(arc_data, byref(header_data)) != 0:
|
||||
raise UnRARException('%s has no files'%path)
|
||||
file_name = header_data.FileNameW
|
||||
if is_match(file_name):
|
||||
PFCode = _libunrar.RARProcessFileW(arc_data, RAR_EXTRACT, None, None)
|
||||
if PFCode != 0:
|
||||
raise UnRARException(_interpret_process_file_error(PFCode))
|
||||
return header_data.FileNameW.replace('/', os.sep), \
|
||||
open(os.path.join(dir, *header_data.FileNameW.split('/')), 'rb').read()
|
||||
else:
|
||||
PFCode = _libunrar.RARProcessFileW(arc_data, RAR_SKIP, None, None)
|
||||
if PFCode != 0:
|
||||
raise UnRARException(_interpret_process_file_error(PFCode))
|
||||
|
||||
finally:
|
||||
_libunrar.RARCloseArchive(arc_data)
|
||||
|
||||
path = os.path.abspath(path)
|
||||
if as_file:
|
||||
path = _extract_member(path, match, name)
|
||||
return path, open(path, 'rb')
|
||||
else:
|
||||
with TemporaryDirectory('_libunrar') as tdir:
|
||||
with CurrentDir(tdir):
|
||||
path = _extract_member(path, match, name)
|
||||
return path, open(path, 'rb').read()
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user