Подсчитайте длину (количество строк) файла 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] содержит содержимое файла temp/uploaded, а не путь к файлу. И я не знаю, как извлечь количество строк в моем исходном файле. Каков правильный способ получить количество строк в файле?

My 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.

Ответы

Ответ 1

другой способ прочитать количество строк:

file.readlines.size

Ответ 2

.length и .size - фактически синонимы. чтобы получить номер строки csv файла, который вы должны проанализировать. просто подсчет строк в файле не будет работать, потому что в строковых полях в csv могут быть разрывы строк. простой способ получить linecount будет:

CSV.read(params[:upcsv][:filename]).length

Ответ 3

Все перечисленные здесь решения фактически загружают весь файл в память, чтобы получить количество строк. Если вы используете систему на базе Unix, гораздо быстрее, проще и эффективнее с точки зрения памяти решение:

`wc -l #{your_file_path}`.to_i

Ответ 4

CSV.foreach(file_path, headers: true).count

Выше будет заголовок exclue при подсчете строк

CSV.read(file_path).count

Ответ 5

your_csv.count должен сделать трюк.

Ответ 6

Просто, чтобы продемонстрировать, что читает IO # readlines:

если у вас есть такой файл: "Asdflkjasdlkfjsdakf\п asdfjljdaslkdfjlsadjfasdflkj\п asldfjksdjfa\п "

в рельсах, которые вы сделали бы, скажите:

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 # может быть очень полезно при работе с файлами, которые имеют повторяющуюся структуру строки ( "child_id", "parent_ary", "child_id", "parent_ary",...) и т.д.

Ответ 7

Если ваш файл csv не подходит для памяти (не может использовать строки чтения), вы можете сделать:

def self.line_count(f)
  i = 0
  CSV.foreach(f) {|_| i += 1}
  i
end

В отличие от wc -l, это подсчитывает фактическое количество записей, а не количество строк. Они могут быть разными, если в значениях полей есть новые строки.