我正在尝试确定要转储到 MySQL 表中的包含 300 多个字段的大型 CSV 文件 (~5GB) 的最大字段大小。我为该文件提供的 CSV 文件架构提供了不正确的最大字段长度,因此我在导入表时遇到错误。我在 Windows 上运行 Ruby 2.0。
我正在使用一个数组来根据字段的索引(或列)位置存储最大字段长度,即忽略标题中的字段实际名称。我尝试过更高级的东西,比如使用哈希、注入和 zip 等,但似乎一个简单的数组在这里工作得最快。
field_lengths[0] = Max length of first field
field_lengths[1] = Max length of second field
etc.
该文件太大而无法一次 slurp 或使用 CSV 逐列解析。因此,我打开 CSV 文件并使用 CSV#foreach 解析每一行(使用 :headers => true 选项忽略标题)。对于每一行,我遍历解析的字段值数组,并将字段的长度与存储在 field_length 数组中的当前最大长度进行比较。我意识到有更简单的方法可以使用较小的文件来做到这一点。此方法适用于较大的文件,但我仍然无法使用此方法使其到达特定文件的末尾。
为了避免无法完成文件,我目前定义了许多要读取的行,包括标题 (=n),并在我到达第 n 行时中断。在下面的示例中,我从 CSV 文件中读取了 101 行。(1 个标题行 + 100 个实际数据行)。我不确定文件中有多少行,因为该过程尚未完成。
require 'csv'
require 'pp'
data_file = 'big_file.csv'
# We're only reading the first 101 lines in this example
n = 101
field_lengths = []
File.open(data_file) do |f|
CSV.foreach(f, :headers => true, :header_converters => :symbol) do |csv_row|
break if $. > n
csv_row.fields.each_with_index do |a,i|
field_lengths[i] ||= a.to_s.length
field_lengths[i] = a.to_s.length if field_lengths[i] < a.to_s.length
end
end
end
pp field_lengths
IO#read 可以读取一定数量的字节,但如果我按字节解析文件,记录可能会被拆分。有没有人有其他建议来解析 CSV 文件,将其拆分为较小的文件?O'Reilly 的 Ruby Cookbook(Lucas Carlson 和 Leonard Richardson,2006 年,第 1 版)建议将大文件分成块(如下所示),但我不确定如何将其扩展到此示例,特别是处理换行符等等
class File
def each_chunk(chunk_size = 1024)
yield read(chunk_size) until eof?
end
end
open("bigfile.txt") do |f|
f.each_chunk(15) {|chunk| puts chunk}
end