The size parameter for gzip.open().read()



在Python中使用gzip库时,我经常会遇到以如下模式使用.read()函数的代码:

with gzip.open(filename) as bytestream:
bytestream.read(16) 
buf = bytestream.read(
IMAGE_SIZE * IMAGE_SIZE * num_images * NUM_CHANNELS
)
data = np.frombuffer(buf, dtype=np.uint8).astype(np.float32)

虽然我熟悉上下文管理器模式,但我很难真正理解with上下文管理器中的第一行代码到底在做什么。

这是read()函数的文档:

从流中最多读取n个字符。

从底层缓冲区读取,直到我们有n个字符或达到EOF。如果n为负数或忽略,则读取直到EOF。

如果是这样的话,第一行bytestream.read(16)的功能作用必须是读取并跳过前16个字符,可能是因为它们充当元数据或标头。但是,当我有一些图像时,我怎么知道使用16作为read调用的参数,而不是32、8或64?

我记得有很多次遇到与上面完全相同的代码,只是让作者使用bytestream.read(8)而不是bytestream.read(16),或者很可能使用任何其他值。逐个字符地挖掘文件显示没有可识别的模式来确定头字符的长度。

换句话说,如何确定要在read函数调用中使用的参数或者如何知道gzip压缩文件中头字符的长度?

我的猜测是它与字节有关,但在搜索了文档和在线参考资料后,我无法证实这一点。

可复制细节

经过无数小时的故障排除,我的假设是,前16个字符代表某种标题或元数据。因此,该代码的第一行是跳过16个字符,并将剩余字符存储在名为buf的变量中。然而,在深入研究数据后,我发现无法确定为什么或如何选择值16。我已经逐个字符地读取了字节,并尝试将其读取+铸造为np.float,但没有明显的模式表明元数据在第16个字符结束,实际数据在第17个字符开始。

以下代码从该网站读取数据并提取前30个字符。请注意,头行"结束"的位置(显然是第16位,在第二次出现\x1c`之后)和数据开始的位置是不可分辨的:

import gzip
import numpy as np
train_data_filename = 'data_input/train-images-idx3-ubyte.gz'
IMAGE_SIZE = 28
NUM_CHANNELS = 1
def extract_data(filename, num_images):
with gzip.open(filename) as bytestream:
first30 = bytestream.read(30)
return first30
first30= extract_data(train_data_filename, 10)
print(first30)
# returns: b'x00x00x08x03x00x00xea`x00x00x00x1cx00x00x00x1cx00x00x00x00x00x00x00x00x00x00x00x00x00x00'

如果我们修改代码以将它们强制转换为np.float32,使得所有字符现在都是数字(浮点),那么就没有明显的模式来区分头/元数据的结束位置和数据的开始位置。

如有任何参考或建议,我们将不胜感激!

从gzip的角度来看,它返回给您的一切都是数据。没有元数据或特定于gzip的标头内容被预处理到该数据流中,因此不需要任何类型的算法来计算gzip在该流中预处理了多少内容:它预处理的字节数为零。


向下滚动到链接页面的底部;有一个标题为MNIST数据库的文件格式的标题。

该格式规范告诉您格式是什么,因此每个头使用了多少字节。具体来说,每个文件中的前四项描述如下:

0000     32 bit integer  0x00000803(2051) magic number 
0004     32 bit integer  60000            number of images 
0008     32 bit integer  28               number of rows 
0012     32 bit integer  28               number of columns 

因此,如果你想跳过这四个项目,你需要从顶部去掉16个字节。

从代码片段中,bytestream.read(16)读取或跳过字节流的前16个字节。当您引用read()从流中最多读取n个字符时,它确实这样做了,但python似乎在1个字节中存储了一个字符,使16个字符占据了16个字节。

查看有关字符和字节的更多信息https://pymotw.com/3/gzip/#reading-压缩数据

代码片段主要对buf的内容感兴趣,跳过流的前16个字节。要了解如何确定进入第一个bytestream.read()AKA的参数来确定要跳过压缩图像文件的多少字节,我们必须了解代码的其余部分。特别是,我们正在读取什么文件,以及我们试图用numpy(?)库完成什么(将rgb图像保存在1D numpy数组中?)。

我绝对不是图像处理方面的专家,但bytestream.read(16)似乎是处理某些独特压缩图像文件的独特问题的独特解决方案。因此,如果没有看到更多的代码和理解代码片段背后的更多逻辑,很难判断如何确定要跳过多少字节。

相关内容

最新更新