【问题标题】:Ruby - checking if file is a CSVRuby - 检查文件是否为 CSV
【发布时间】:2015-10-17 09:45:12
【问题描述】:

我刚刚编写了一个代码,其中我得到了一个传入参数的 csv 文件并逐行处理它;到目前为止,一切都很好。现在,我想通过确保我们在参数中收到的是一个 .csv 文件来保护我的代码。

我在 Ruby 文档中看到它存在一个 == "--file" 选项,但使用它会产生错误:按照我的理解,这个选项似乎只适用于 txt 文件。

是否有特定的方法可以检查我的文件是否为 csv ?这是我的一些代码:

    if ARGV.empty?
       puts "j'ai rien reçu"
    # option to check, don't work 
    elsif ARGV[0].shift == "--file"

    # my code so far, whithout checking  
    else  CSV.foreach(ARGV.shift) do |row|

等等等等……

【问题讨论】:

  • 是的,通过一个简单的命令行:./nameofmyscript nameofmyfile

标签: ruby-on-rails ruby csv


【解决方案1】:

我认为在没有额外信息的情况下进行真正安全的测试是不可能的。

请注意您可以做什么: 您在变量文件名中获得一个文件名。

首先,检查是否是文件:

File.exist?

然后你可以检查一下,编码是否正确:

raise "Wrong encoding" unless content.valid_encoding?

您的 csv 是否始终具有相同的列数?你只有一个班轮吗? 这可能是进行下一次检查的可能性:

content.each_line{|line|
  return false if line.count(sep) < columns - 1
}

可以根据您的情况修改此检查,例如如果你总是有一个确切的行数。

总的来说,您可以定义如下内容:

require 'csv'
#columns defines the expected numer of columns per line
def csv?(filename, sep: ';', columns: 3)
  return false unless File.exist?(filename) #"No file" 
  content = File.read(filename, :encoding => 'utf-8')
  return false unless content.valid_encoding? #"Wrong encoding" 

  content.each_line{|line|
    return false if line.count(sep) < columns - 1
  }
  CSV.parse(content, :col_sep => sep)

end

if csv = csv?('test.csv')
  csv.each do |row|
    p row
  end
end

【讨论】:

  • 如果某些字段被引用并且有新行,则无法检查列数,因为这样的行将被拆分为多行。
【解决方案2】:

你可以使用ruby-filemagicgem

gem install ruby-filemagic

用法:

$ irb 
irb(main):001:0> require 'filemagic' 
=> true
irb(main):002:0> fm = FileMagic.new
=> #<FileMagic:0x7fd4afb0>
irb(main):003:0> fm.file('foo.zip') 
=> "Zip archive data, at least v2.0 to extract"
irb(main):004:0>

https://github.com/ricardochimal/ruby-filemagic

【讨论】:

  • 感谢您的回答。是的,这是一个好主意,但我担心,如果我将脚本传输到另一台机器并且没有安装 gem,它将无法工作。你确定Ruby中没有直接的方法吗?
  • 如果你为你的应用程序创建了一个 gem,你可以在你的 gemspec 文件中添加以下行:add_runtime_dependency('ruby-filemagic'),它将作为依赖项安装。
  • 这就是与宝石的交易。这就是 RubyGems 如此酷的原因。你可以很容易地通过你的 gemfile 来完成。不要害怕兄弟!
【解决方案3】:

使用File.extname()检查源文件

File.extname("test.rb")         #=> ".rb"

【讨论】:

  • 是的,但这只是检查不安全的扩展。
  • 我试过了,效果很好。对我来说似乎是一个很好的解决方案。谢谢,Artyom
  • 因此,如果我采用 mpeg 文件并将扩展名更改为 .csv,则您的测试通过了。如果您需要 100% 安全,则需要检查内容类型!
  • MIME::Types.type_for(@some_file).first.content_type
  • 文件的扩展名与其内容无关。扩展名是一些应用程序用作文件内容提示的字符串,但不能保证内容是该文件类型。嗅探文件的内容是一种更有效的测试,但即使是“魔法”测试也不会查看文件中的每个字节。
猜你喜欢
  • 2021-03-21
  • 1970-01-01
  • 2018-01-03
  • 2017-07-21
  • 2011-10-03
  • 2011-02-28
  • 2012-02-12
  • 2015-10-24
  • 1970-01-01
相关资源
最近更新 更多