Ruby:如何将文件拆分为给定大小的多个文件

标签 ruby file split size

我想将一个 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/

相关文章:

ruby-on-rails - block 范围不一致之前的 Rspec

ruby - 将 Sinatra 设置为在子目录中运行

string - 将具有相似名称的文件连接在一起

python - 如何在 Python 中将整个字符串写入文件以及文件的位置?

arrays - Windows 批处理静态列表重命名-移动

javascript - 在单个索引数组中的数字处分割字符串以形成新的索引 javascript

ruby-on-rails - Net HTTP Persistent/Keep Alive with Ruby OAuth2 gem

html - 用于缩放的响应式图像高度和宽度百分比?

r - 在 R 中分割字符串,不同的分割参数元素

javascript - 拆分而不丢失分隔符