maa*_*sha 7 ruby size split file
我想将一个txt文件拆分成多个文件,其中每个文件包含不超过5Mb.我知道有这方面的工具,但我需要这个项目,并希望在Ruby中做到这一点.另外,如果可能的话,我更喜欢在块上下文中使用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
Run Code Online (Sandbox Code Playgroud)
这项工作,但我认为它不优雅.此外,我仍然想知道是否可以在块上下文中使用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
Run Code Online (Sandbox Code Playgroud)
干杯,
马丁
asa*_*aki 17
[更新]写了一个没有任何辅助变量的简短版本,并将所有内容放在一个方法中:
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)
Run Code Online (Sandbox Code Playgroud)
您可以使用.read(length)并仅为EOF标记和文件光标执行循环,而不是行循环.
这使得粗块文件永远不会超过您想要的块大小.
另一方面,它永远不会关注换行符(\n)!
块文件的编号将通过chunksize从当前文件光标位置的整数除法生成,格式为"%05d",导致带有前导零(00001)的5位数字.
这是唯一可行的,因为.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|
line = ""
while fh_out.size <= (chunksize-line.length) && !fh_in.eof?
line = fh_in.readline
fh_out << line
end
end
outfilenum += 1
end
end
end
Run Code Online (Sandbox Code Playgroud)
我已经向大家介绍一个辅助变量line,因为我想确保矮胖文件大小总是低于该chunksize极限!如果您不进行此扩展检查,您将获得超出限制的文件大小.该while语句仅在已经写入行时成功检查下一个迭代步骤.(使用.ungetc或其他复杂的计算将使代码更难以阅读并且不会比此示例更短.)
不幸的是,您必须进行第二次EOF检查,因为最后一次块迭代将主要导致较小的块.
还需要两个辅助变量:line如上所述,outfilenum需要这样做,因为生成的文件大小大多与精确不匹配chunksize.
Way*_*rad 12
对于任何大小的文件,split将比临时构建的Ruby代码更快,甚至考虑到启动单独的可执行文件的成本.它也是您不必编写,调试或维护的代码:
system("split -C 1M -d test.txt ''")
Run Code Online (Sandbox Code Playgroud)
选项是:
-C 1M 在每个块中放置总计不超过1M的行-d 在输出文件名中使用十进制后缀test.txt 输入文件的名称'' 使用空白输出文件前缀除非你在Windows上,否则这就是你要走的路.