gpt4 book ai didi

ruby - 如何有效地将文件拆分为 ruby​​ 中的任意字节范围

转载 作者:行者123 更新时间:2023-12-04 03:35:08 28 4
gpt4 key购买 nike

我需要将大文件上传到第三方服务。这个第三方服务给了我一个 url 和 byteranges 的列表:

requests = [
{url: "https://.../part1", from: 0, to: 20_000_000},
{url: "https://.../part2", from: 20_000_001, to: 40_000_000},
{url: "https://.../part3", from: 40_000_001, to: 54_184_279}
]

我正在使用 httpx gem要上传数据,:body 选项可以接收一个IOEnumerable 对象。我想以一种有效的方式拆分和上传 block 。这就是为什么我认为我应该避免将 block 写入磁盘并避免将整个文件加载到内存中。我想最好的选择是某种“惰性可枚举”,但我不知道如何编写返回此 IOEnumerable< 的 part 函数 对象。

file = File.open("bigFile", "rb")
results = requests.each do |request|
Thread.start { HTTPX.post(request[:url]), body: part(file, request[:from], request[:to]) }
end.map(&:value)

def part(file, from, to)
# ???
end

最佳答案

为每个“byterange”生成枚举器的最简单方法是让 part 函数处理文件的打开:

def part(filepath, from, to = nil, chunk_size = 4096, &block)
return to_enum(__method__, filepath, from, to, chunk_size) unless block_given?
size = File.size(filepath)
to = size-1 unless to and to >= from and to < size
io = File.open(filepath, "rb")
io.seek(from, IO::SEEK_SET)
while (io.pos <= to)
size = (io.pos + chunk_size <= to) ? chunk_size : 1 + to - io.pos
chunk = io.read(size)
yield chunk
end
ensure
io.close if io
end

警告:chunk size计算可能有误,过会儿我会查看(我还要照顾 child )

注意:您可能希望改进此功能以确保您始终读取完整的物理硬盘 block (或多个物理硬盘 block ),因为它会大大加快 IO。 from 不是物理 HDD block 的倍数时,您会出现错位。

part 函数现在在没有 block 的情况下调用时返回一个 Enumerator:

part("bigFile", 0, 1300, 512)
#=> #<Enumerator: main:part("bigFile", 0, 1300, 512)

当然你可以直接用 block 调用它:

part("bigFile", 0, 1300, 512) do |chunk|
puts "#{chunk.inspect}"
end

关于ruby - 如何有效地将文件拆分为 ruby​​ 中的任意字节范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67058590/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com