BytesIO.truncate 方法不扩展缓冲区内容
BytesIO.truncate method does not extend buffer contents
IOBase.truncate
方法的文档说:
truncate(size=None)
Resize the stream to the given size in bytes (or the current position if size is not specified). The current stream position isn’t changed. This resizing can extend or reduce the current file size. In case of extension, the contents of the new file area depend on the platform (on most systems, additional bytes are zero-filled). The new file size is returned.
Changed in version 3.5: Windows will now zero-fill files when extending.
因此,考虑到这一点,我假设 BytesIO
(BufferedIOBase
的子类又是 IOBase
的子类)在此之后更改其内部缓冲区大小方法已被调用。
但是下面的代码片段表明我的假设是错误的:
from io import BytesIO
# prints b'\x00\x00\x00\x00\x00\x00\x00\x00'
data = BytesIO(8 * b"\x00")
print(data.getvalue())
# prints 16
print(data.truncate(16))
# prints b'\x00\x00\x00\x00\x00\x00\x00\x00'
print(data.getvalue())
# prints b'\x00\x00\x00\x00\x00\x00\x00\x00'
print(bytes(data.getbuffer()))
我哪里转错了?
检查 source code,文档似乎不是最新的 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
IOBase.truncate
方法的文档说:
truncate(size=None)
Resize the stream to the given size in bytes (or the current position if size is not specified). The current stream position isn’t changed. This resizing can extend or reduce the current file size. In case of extension, the contents of the new file area depend on the platform (on most systems, additional bytes are zero-filled). The new file size is returned.
Changed in version 3.5: Windows will now zero-fill files when extending.
因此,考虑到这一点,我假设 BytesIO
(BufferedIOBase
的子类又是 IOBase
的子类)在此之后更改其内部缓冲区大小方法已被调用。
但是下面的代码片段表明我的假设是错误的:
from io import BytesIO
# prints b'\x00\x00\x00\x00\x00\x00\x00\x00'
data = BytesIO(8 * b"\x00")
print(data.getvalue())
# prints 16
print(data.truncate(16))
# prints b'\x00\x00\x00\x00\x00\x00\x00\x00'
print(data.getvalue())
# prints b'\x00\x00\x00\x00\x00\x00\x00\x00'
print(bytes(data.getbuffer()))
我哪里转错了?
检查 source code,文档似乎不是最新的 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