@@ -847,6 +847,7 @@ def __init__(self, fileobj, mode, zipinfo, pwd=None,
847
847
self ._orig_compress_size = zipinfo .compress_size
848
848
self ._orig_file_size = zipinfo .file_size
849
849
self ._orig_start_crc = self ._running_crc
850
+ self ._orig_crc = self ._expected_crc
850
851
self ._seekable = True
851
852
except AttributeError :
852
853
pass
@@ -1069,17 +1070,17 @@ def seekable(self):
1069
1070
raise ValueError ("I/O operation on closed file." )
1070
1071
return self ._seekable
1071
1072
1072
- def seek (self , offset , whence = 0 ):
1073
+ def seek (self , offset , whence = os . SEEK_SET ):
1073
1074
if self .closed :
1074
1075
raise ValueError ("seek on closed file." )
1075
1076
if not self ._seekable :
1076
1077
raise io .UnsupportedOperation ("underlying stream is not seekable" )
1077
1078
curr_pos = self .tell ()
1078
- if whence == 0 : # Seek from start of file
1079
+ if whence == os . SEEK_SET :
1079
1080
new_pos = offset
1080
- elif whence == 1 : # Seek from current position
1081
+ elif whence == os . SEEK_CUR :
1081
1082
new_pos = curr_pos + offset
1082
- elif whence == 2 : # Seek from EOF
1083
+ elif whence == os . SEEK_END :
1083
1084
new_pos = self ._orig_file_size + offset
1084
1085
else :
1085
1086
raise ValueError ("whence must be os.SEEK_SET (0), "
@@ -1094,14 +1095,27 @@ def seek(self, offset, whence=0):
1094
1095
read_offset = new_pos - curr_pos
1095
1096
buff_offset = read_offset + self ._offset
1096
1097
1097
- if buff_offset >= 0 and buff_offset < len (self ._readbuffer ):
1098
+ # Fast seek uncompressed unencrypted file
1099
+ if self ._compress_type == ZIP_STORED and self ._decrypter is None and read_offset > 0 :
1100
+ # disable CRC checking after first seeking - it would be invalid
1101
+ self ._expected_crc = None
1102
+ # seek actual file taking already buffered data into account
1103
+ read_offset -= len (self ._readbuffer ) - self ._offset
1104
+ self ._fileobj .seek (read_offset , os .SEEK_CUR )
1105
+ self ._left -= read_offset
1106
+ read_offset = 0
1107
+ # flush read buffer
1108
+ self ._readbuffer = b''
1109
+ self ._offset = 0
1110
+ elif buff_offset >= 0 and buff_offset < len (self ._readbuffer ):
1098
1111
# Just move the _offset index if the new position is in the _readbuffer
1099
1112
self ._offset = buff_offset
1100
1113
read_offset = 0
1101
1114
elif read_offset < 0 :
1102
1115
# Position is before the current position. Reset the ZipExtFile
1103
1116
self ._fileobj .seek (self ._orig_compress_start )
1104
1117
self ._running_crc = self ._orig_start_crc
1118
+ self ._expected_crc = self ._orig_crc
1105
1119
self ._compress_left = self ._orig_compress_size
1106
1120
self ._left = self ._orig_file_size
1107
1121
self ._readbuffer = b''
0 commit comments