Подсчитать длину (количество строк) файла CSV?
У меня есть форма (Rails), которая позволяет мне загрузить файл.csv, используя file_field
, По мнению:
<% form_for(:upcsv, :html => {:multipart => true}) do |f| %>
<table>
<tr>
<td><%= f.label("File:") %></td>
<td><%= f.file_field(:filename) %></td>
</tr>
</table>
<%= f.submit("Submit") %>
<% end %>
Нажатие "Отправить" перенаправляет меня на другую страницу (create.html.erb). Файл был загружен нормально, и я смог прочитать содержимое на этой второй странице. Я пытаюсь показать количество строк в файле.csv на этой второй странице.
Мой контроллер (полупсевдокод):
class UpcsvController < ApplicationController
def index
end
def create
file = params[:upcsv][:filename]
...
#params[:upcsv][:file_length] = file.length # Show number of lines in the file
#params[:upcsv][:file_length] = file.size
...
end
end
И то и другое file.length
а также file.size
возвращает "91", когда мой файл содержит только 7 строк. Из документации по Rails, которую я прочитал, после нажатия кнопки "Отправить" Rails создает временный файл загруженного файла, и params[:upcsv][:filename]
содержит содержимое временного / загруженного файла, а не путь к файлу. И я не знаю, как извлечь количество строк в моем исходном файле. Как правильно получить количество строк в файле?
Мой create.html.erb:
<table>
<tr>
<td>File length:</td>
<td><%= params[:upcsv][:file_length] %></td>
</tr>
</table>
Я действительно новичок в Rails (только начался на прошлой неделе), поэтому, пожалуйста, ответьте на мои глупые вопросы
Спасибо!
Обновление: очевидно, что число "91" - это количество отдельных символов (включая возврат каретки) в моем файле. Каждая строка в моем файле имеет 12 цифр + 1 символ новой строки = 13. 91/13 = 7.
7 ответов
Все решения, перечисленные здесь, фактически загружают весь файл в память для получения количества строк. Если вы работаете в Unix-системе, гораздо более быстрое, простое и эффективное использование памяти:
`wc -l #{your_file_path}`.to_i
.length и.size на самом деле являются синонимами. чтобы получить количество строк в CSV-файле, вам нужно его проанализировать. простой подсчет новых строк в файле не сработает, потому что в строковых полях в csv действительно могут быть разрывы строк. простой способ получить количество строк:
CSV.read(params[:upcsv][:filename]).length
CSV.foreach(file_path, headers: true).count
Выше будет исключать заголовок при подсчете строк
CSV.read(file_path).count
Если ваш CSV-файл не помещается в память (не может использовать readlines), вы можете сделать:
def self.line_count(f)
i = 0
CSV.foreach(f) {|_| i += 1}
i
end
В отличие от wc -l
это подсчитывает фактическое количество записей, а не количество строк. Они могут отличаться, если в значениях полей появляются новые строки.
Просто чтобы продемонстрировать, что делает IO#readlines:
если у вас есть такой файл: "asdflkjasdlkfjsdakf\n asdfjljdaslkdfjlsadjfasdflkj\n asldfjksdjfa\n"
в рельсах ты сказал бы:
file = File.open(File.join(Rails.root, 'lib', 'file.json'))
lines_ary = IO.readlines(file)
lines_ary.count #=> 3
IO#readlines преобразует файл в массив строк, используя \n (новые строки) в качестве разделителей, так же, как это часто делают запятые, так что это в основном похоже на
str.split(/\n/)
На самом деле, если вы сделали
x = file.read
этот
x.split(/\n/)
будет делать то же самое, что и file.readlines
** IO # readline может быть очень удобно при работе с файлами, которые имеют структуру повторяющейся строки ("child_id", "parent_ary", "child_id", "parent_ary",...) и т. Д.