计算CSV文件的长度(行数)?

时间:2011-01-11 20:46:02

标签: ruby-on-rails ruby csv

我有一个表单(Rails),它允许我使用file_field加载.csv文件。 在视图中:

    <% 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

当我的文件只包含7行时,file.lengthfile.size都会返回'91'。从我阅读的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 个答案:

答案 0 :(得分:20)

此处列出的所有解决方案实际上都会将整个文件加载到内存中以获取行数。如果您使用的是基于Unix的系统,则可以使用更快,更简单且更节省内存的解决方案:

`wc -l #{your_file_path}`.to_i

答案 1 :(得分:16)

.length和.size实际上是同义词。要获取csv文件的rowcount,你必须实际解析它。简单地计算文件中的换行符是行不通的,因为csv中的字符串字段实际上可以有换行符。获得行数的简单方法是:

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

答案 2 :(得分:14)

读取行数的另一种方法是

file.readlines.size

答案 3 :(得分:5)

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

上面会在计数行时删除标题

CSV.read(file_path).count

答案 4 :(得分:1)

your_csv.count应该可以解决问题。

答案 5 :(得分:0)

只是为了演示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 #readlines在处理具有重复行结构的文件(“child_id”,“parent_ary”,“child_id”,“parent_ary”,......)等时非常方便

答案 6 :(得分:0)

如果你的csv文件不适合内存(不能使用readlines),你可以这样做:

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

wc -l不同,这会计算实际记录数,而不是行数。如果字段值中有新行,则这些可能会有所不同。