我想将一个 txt 文件拆分成多个文件,每个文件包含的内容不超过 5Mb。我知道有这方面的工具,但我的项目需要这个,并且想在 Ruby 中完成。此外,如果可能的话,我更喜欢在 block 上下文中使用 File.open 来执行此操作,但我失败了 :o(
#!/usr/bin/env ruby
require 'pp'
MAX_BYTES = 5_000_000
file_num = 0
bytes = 0
File.open("test.txt", 'r') do |data_in|
File.open("#{file_num}.txt", 'w') do |data_out|
data_in.each_line do |line|
data_out.puts line
bytes += line.length
if bytes > MAX_BYTES
bytes = 0
file_num += 1
# next file
end
end
end
end
这项工作,但我认为它并不优雅。另外,我仍然想知道是否可以仅在 block 上下文中使用 File.open 来完成。
#!/usr/bin/env ruby
require 'pp'
MAX_BYTES = 5_000_000
file_num = 0
bytes = 0
File.open("test.txt", 'r') do |data_in|
data_out = File.open("#{file_num}.txt", 'w')
data_in.each_line do |line|
data_out = File.open("#{file_num}.txt", 'w') unless data_out.respond_to? :write
data_out.puts line
bytes += line.length
if bytes > MAX_BYTES
bytes = 0
file_num += 1
data_out.close
end
end
data_out.close if data_out.respond_to? :close
end
干杯,
马丁
最佳答案
[更新] 编写了一个简短的版本没有任何辅助变量并将所有内容放在一个方法中:
def chunker f_in, out_pref, chunksize = 1_073_741_824
File.open(f_in,"r") do |fh_in|
until fh_in.eof?
File.open("#{out_pref}_#{"%05d"%(fh_in.pos/chunksize)}.txt","w") do |fh_out|
fh_out << fh_in.read(chunksize)
end
end
end
end
chunker "inputfile.txt", "output_prefix" (, desired_chunk_size)
您可以使用 .read(length)
代替循环线并只为 EOF
做一个循环标记和文件光标。
这会确保大块文件永远不会大于您想要的 block 大小。
另一方面,它从不关心换行符 (\n
)!
block 文件的编号将从当前文件光标位置除以 block 大小的整数除法生成,格式为“%05d”,结果是前导零的 5 位数字 (00001
)。
这是可能的,因为 .read(chunksize)
用来。在下面的第二个例子中,它无法使用!
更新: 使用换行符识别拆分
如果你真的需要完整的行 \n
然后使用这个修改后的代码片段:
def chunker f_in, out_pref, chunksize = 1_073_741_824
outfilenum = 1
File.open(f_in,"r") do |fh_in|
until fh_in.eof?
File.open("#{out_pref}_#{outfilenum}.txt","w") do |fh_out|
loop do
line = fh_in.readline
fh_out << line
break if fh_out.size > (chunksize-line.length) || fh_in.eof?
end
end
outfilenum += 1
end
end
end
我不得不引入一个辅助变量 line
因为我想确保大文件大小始终低于 chunksize
限制!如果您不执行此扩展检查,您也会得到超过限制的文件大小。 while
语句仅在该行已写入时才成功检查下一个迭代步骤。 (使用 .ungetc
或其他复杂的计算将使代码更难读,并且不会比此示例更短。)
不幸的是你必须有第二个EOF
检查,因为最后的 block 迭代将主要导致更小的 block 。
还需要两个辅助变量:line
如上所述,outfilenum
是必需的,因为生成的文件大小大多与精确的 chunksize
不匹配.
关于Ruby:如何将文件拆分为给定大小的多个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6150227/