在Python中将重复字节流转换为IO

x759pob2  于 2023-11-20  发布在  Python
关注(0)|答案(2)|浏览(96)

我正在写一个程序,需要在Python中向文件中写入大量重复的字节。
为了简化问题,我将使用数据的表示。buffer总是open(file_name, "a+")的返回结果,b"0"将是“重复数据”的任意表示。
假设我想写重复的数据50,000次,到目前为止,我想到了三种方法。
第一种方法是先在内存中生成数据,然后写入(这会占用大量内存)

data = b"0" * 50_000
buffer.write(data)

字符串
第二种方法是将每次迭代写在一个循环中(这是极其缓慢的)

for _ in range(50_000):
    buffer.write(b"0")


最后,第三种方法是合并结合两者,并写入更大的段(这比第二种方法快得多,但比第一种方法慢,最重要的是,即使在使用中也会使用内存,加上总体上这种设计非常丑陋)

data_x1 = b"0"
data_x10 = b"0" * 10
data_x100 = b"0" * 100
data_x1000 = b"0" * 1000

# writing in a loop using bigger to smaller segments
# until there is no more to write
num_left = 50_000
while num_left > 0:
    if num_left >= 1000:
        buffer.write(data_x1000)
        num_left -= 1000
    elif num_left >= 100:
        buffer.write(data_x100)
        num_left -= 100
    elif num_left >= 10:
        buffer.write(data_x10)
        num_left -= 10
    else:
        buffer.write(data_x1)
        num_left -= 1


TLDR:目标是在不使用Python循环的情况下重复地将指定的字节集写入文件,也不首先在内存中生成整个序列。
我一直在研究BufferedWriter的write方法,注意到它需要一个类似字节的对象。如果可能的话,最佳的方法是创建一个“类似字节”的对象,模拟一个重复的数据流,可以在不使用Python循环的情况下由缓冲区写入x次。

ubbxdtey

ubbxdtey1#

只需合理地创建最大的数据块,并将最后一次写入的数据切片得更小

# largest block you can put into memory
# replicate block until some limit
# must wrap at end if data isn't all the same
data = b"0" * 50_000

added_length = 120_000

with open(file_name, "ab+") as fh:  # bytes mode makes math work
    while fh.tell() < added_length:
        fh.write(data[:added_length - fh.tell()])  # don't write too much

字符串
请注意,当打开"a"时,.tell()将从0开始,并且与初始文件结尾有 * 偏移量 *。然而,如果您想在同一个文件中读取其他内容或获取总文件大小,您可能会发现将"r+".seek()打开到结尾更好。

bis0qfac

bis0qfac2#

如果你打算尝试使用大缓冲区写,你可能最好使用系统默认的缓冲区大小。

import io
data = b'0' * io.DEFAULT_BUFFER_SIZE
full, extra = divmod(total_bytes_to_write, io.DEFAULT_BUFFER_SIZE)
with open(file_name, "ab+") as fh:
    for _ in range(full):
        fh.write(data)
    fh.write(data[:extra]

字符串
您可能会通过使用默认缓冲区大小的倍数来获得一点好处,但是一定要在open命令中使用这个值。

import io
buffer_size = 4 * io.DEFAULT_BUFFER_SIZE
data = b'0' * buffer_size
full, extra = divmod(total_bytes_to_write, buffer+size)
with open(file_name, "ab+", buffering=buffer_size) as fh:
    .. same as above ...


用户@trapdrap(见评论)声称,在所有情况下,你都应该使用buffering = 0,因为你不想或不需要缓冲。

相关问题