BytesIO.truncate 方法不扩展缓冲区内容



IOBase.truncate方法的文档说:

截断(大小=无(

将流的大小调整为给定的大小(以字节为单位((如果未指定大小,则调整为当前位置(。当前流位置不会更改。此大小调整可以扩展或减小当前文件大小。在扩展的情况下,新文件区域的内容取决于平台(在大多数系统上,额外的字节是零填充的(。将返回新的文件大小。

在 3.5 版更改: Windows 现在在扩展时将零填充文件。

因此,考虑到这一点,我认为BytesIO(这是BufferedIOBase的子类,又是IOBase的子类(在调用此方法后会更改其内部缓冲区大小。

但是下面的代码片段表明我的假设是错误的:

from io import BytesIO
# prints b'x00x00x00x00x00x00x00x00'
data = BytesIO(8 * b"x00")
print(data.getvalue())
# prints 16
print(data.truncate(16))
# prints b'x00x00x00x00x00x00x00x00'
print(data.getvalue())
# prints b'x00x00x00x00x00x00x00x00'
print(bytes(data.getbuffer()))

我哪里走错了路?

检查源代码,似乎文档与BytesIO实现不是最新的:

static PyObject *_io_BytesIO_truncate_impl(bytesio *self, Py_ssize_t size)
/*[clinic end generated code: output=9ad17650c15fa09b input=423759dd42d2f7c1]*/
{
CHECK_CLOSED(self);
CHECK_EXPORTS(self);
if (size < 0) {
PyErr_Format(PyExc_ValueError,    
"negative size value %zd", size);
return NULL;
}
if (size < self->string_size) {    
self->string_size = size;    
if (resize_buffer(self, size) < 0)    
return NULL;   
}
return PyLong_FromSsize_t(size);
}

if (size < self->string_size)测试可确保在大小大于先前大小时不执行任何操作。

我的猜测是,对于真正的文件处理程序,truncate的工作方式类似于底层平台(扩展文件(,但不适用于内存映射处理程序。

如果我们知道它将失败,则可以通过在对象末尾写入来非常简单地模拟所需的行为:

def my_truncate(data,size):
current_size = len(data.getvalue())
if size < current_size:
return data.truncate(size)
elif size == current_size:
return size  # optim
else:
# store current position
old_pos = data.tell()
# go to end
data.seek(current_size)
# write zeroes
data.write(b"x00" * (size-current_size))
# restore previous file position
data.seek(old_pos)
return size

相关内容

  • 没有找到相关文章

最新更新