2013-08-08 13 views
5

Wszystko, co muszę zrobić, to pobrać nagłówki z pliku CSV.Jaki jest najprostszy sposób na uzyskanie nagłówków z pliku CSV w Ruby?

FILE.CSV jest:

"A", "B", "C" 
"1", "2", "3" 

Mój kod to:

table = CSV.open("file.csv", :headers => true) 

puts table.headers 

table.each do |row| 
    puts row 
end 

Który daje mi:

true 
"1", "2", "3" 

Szukałem w dokumentacji Ruby CSV godzinami i to doprowadza mnie do szału. Jestem przekonany, że musi istnieć prosta jednolinijka, która może zwrócić mi nagłówek. Jakieś pomysły?

Odpowiedz

11

Wygląda CSV.read da Ci dostęp do metody headers:

headers = CSV.read("file.csv", headers: true).headers 
# => ["A", "B", "C"] 

powyższe jest naprawdę tylko skrót do CSV.open("file.csv", headers: true).read.headers. Mogłeś się do tego przyzwyczaić używając CSV.open, tak jak próbujesz, ale ponieważ CSV.open nie odczytuje pliku podczas wywoływania metody, nie ma możliwości, aby wiedział on, co to są nagłówki, dopóki nie odczyta niektórych danych. Właśnie dlatego po prostu zwraca true w twoim przykładzie. Po przeczytaniu niektórych danych, by wreszcie powrócić nagłówki:

table = CSV.open("file.csv", :headers => true) 
    table.headers 
    # => true 
    table.read 
    # => #<CSV::Table mode:col_or_row row_count:2> 
    table.headers 
    # => ["A", "B", "C"] 
0

Jeśli chcesz krótsza odpowiedź wtedy można spróbować:

headers = CSV.open("file.csv", &:readline) 
# => ["A", "B", "C"] 
+0

Dobrze wiedzieć, ale ja zdecydować się na bardziej wyraźnej '.headers' podejście @ Dylan-Markow sugeruje. –

3

Moim zdaniem najlepszym sposobem na to jest:

headers = CSV.foreach('file.csv').first

Należy pamiętać, że jej bardzo kuszące, aby korzystać CSV.read('file.csv'. headers: true).headers ale haczyk jest CSV.read ładuje cały plik w pamięci i stąd inc zmniejsza ślad pamięci, a także sprawia, że ​​jest on bardzo wolny w przypadku większych plików. O ile to możliwe, należy użyć CSV.foreach. Poniżej znajdują się odniesienia tylko dla pliku 20 MB:

Ruby version: ruby 2.4.1p111 
File size: 20M 
**************** 
Time and memory usage with CSV.foreach: 
Time: 0.0 seconds 
Memory: 0.04 MB 
**************** 
Time and memory usage with CSV.read: 
Time: 5.88 seconds 
Memory: 314.25 MB 

Plik 20MB pamięci ślad wzrost o 314 MB z CSV.read wyobrazić, co plik 1GB. W skrócie proszę nie używać CSV.read, zrobiłem i system zszedł na plik 300 MB.

Aby uzyskać więcej informacji: Jeśli chcesz przeczytać więcej na ten temat, here to bardzo dobry artykuł na temat obsługi dużych plików.

także poniżej skrypt użyłem benchmarkingu CSV.foreach i CSV.read:

require 'benchmark' 
require 'csv' 
def print_memory_usage 
    memory_before = `ps -o rss= -p #{Process.pid}`.to_i 
    yield 
    memory_after = `ps -o rss= -p #{Process.pid}`.to_i 
    puts "Memory: #{((memory_after - memory_before)/1024.0).round(2)} MB" 
end 

def print_time_spent 
    time = Benchmark.realtime do 
    yield 
    end 
    puts "Time: #{time.round(2)} seconds" 
end 

file_path = '{path_to_csv_file}' 
puts 'Ruby version: ' + `ruby -v` 
puts 'File size:' + `du -h #{file_path}` 
puts 'Time and memory usage with CSV.foreach: ' 
print_memory_usage do 
    print_time_spent do 
    headers = CSV.foreach(file_path, headers: false).first 
    end 
end 
puts 'Time and memory usage with CSV.read:' 
print_memory_usage do 
    print_time_spent do 
    headers = CSV.read(file_path, headers: true).headers 
    end 
end 
Powiązane problemy