Ruby - 检查文件是否为CSV

3

我刚刚写了一段代码,其中我通过参数传递获取一个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 - LittleDev
3个回答

3
我认为如果没有额外的信息,很难进行真正安全的测试。
以下是一些注意事项: 您会在变量“filename”中得到一个文件名。
首先,请检查它是否是一个文件:
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

如果某些字段被引用并且具有换行符,则检查列数将无法正常工作,因为这样的行将跨越多行分割。 - hammady

1
你可以使用 ruby-filemagic gem。
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中没有直接的方法吗? - LittleDev
如果您为您的应用程序创建了一个gem,您可以将以下行添加到您的gemspec文件中:add_runtime_dependency('ruby-filemagic'),它将作为依赖项安装。 - sugaryourcoffee
这就是宝石(Gems)的作用。这就是为什么RubyGems如此酷炫。你可以通过gemfile轻松安装它们。不要害怕! - Tim Kretschmer

-1
使用 File.extname() 检查源文件。
File.extname("test.rb")         #=> ".rb"

是的,但那只是检查扩展名,这是不安全的。 - Tim Kretschmer
我尝试了一下,它可以正常工作。对我来说似乎是一个不错的解决方案。谢谢,Artyom。 - LittleDev
2
如果我将一个 MPEG 文件的扩展名改为 .csv,你的测试会通过。如果你需要百分之百的安全性,你需要检查内容类型! - Tim Kretschmer
MIME::Types.type_for(@some_file).first.content_type - Artyom Kalmykov
文件的扩展名与其内容无关。扩展名是一些应用程序用作文件内容提示的字符串,但这并不保证该内容就是该文件类型。嗅探文件内容是一个更有效的测试方法,但即使是“魔法”测试也不能查看文件中的每个字节,因此可能会被欺骗。 - the Tin Man

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接