Работа с большими файлами CSV в Ruby

Я хочу проанализировать два CSV-файла базы данных MaxMind GeoIP2, выполнить объединение на основе столбца и объединить результат в один выходной файл.

Я использовал стандартную рубиновую библиотеку CSV, она очень медленная. Я думаю, что он пытается загрузить весь файл в память.

block_file = File.read(block_path)
block_csv   = CSV.parse(block_file, :headers => true) 
location_file = File.read(location_path)
location_csv = CSV.parse(location_file, :headers => true)


CSV.open(output_path, "wb",
    :write_headers=> true,
    :headers => ["geoname_id","Y","Z"] ) do |csv|


    block_csv.each do |block_row|
    puts "#{block_row['geoname_id']}"

        location_csv.each do |location_row|
            if (block_row['geoname_id'] === location_row['geoname_id'])
                puts " match :"    
                csv << [block_row['geoname_id'],block_row['Y'],block_row['Z']]
                break location_row
            end
        end

    end

Есть ли другая рубиновая библиотека, поддерживающая обработку по частям?

block_csv — 800 МБ, а location_csv — 100 МБ.


person Okacha Ilias    schedule 19.04.2015    source источник


Ответы (1)


Просто используйте CSV.open(block_path, 'r', :headers => true).each do |line| вместо File.read и CSV.parse. Он будет анализировать файл построчно.

В вашей текущей версии вы явно говорите ему прочитать весь файл с File.read, а затем проанализировать весь файл как строку с CSV.parse. Так что он делает именно то, что вы сказали.

person Oleg K.    schedule 19.04.2015