当前位置: 代码网 > it编程>前端脚本>Ruby > Ruby操作CSV格式数据方法详解

Ruby操作CSV格式数据方法详解

2024年05月15日 Ruby 我要评论
csv格式的数据默认是以逗号分隔各个字段的一条一条记录,默认用换行符分隔每一条记录。此外,有的csv有标题行,有的没有。还有其他一些格式, 它们都有默认值,但都可以在读、写csv数据时修改默认设置。后

csv格式的数据默认是以逗号分隔各个字段的一条一条记录,默认用换行符分隔每一条记录。此外,有的csv有标题行,有的没有。还有其他一些格式, 它们都有默认值,但都可以在读、写csv数据时修改默认设置。后文大多数时候故意忽略这些设置,因为绝大多数读写操作都使用同样的参数**options进行格式设置。例如,在读取csv文件中的数据时想要忽略标题行,可以在参数中设置headers: true 

可设置的项及其默认值包括:

col_sep: ",",                #=> 字段分隔符
row_sep: :auto,              #=> 记录分隔符
quote_char: '"',             #=> 包围字段的符号
field_size_limit: nil,       #=> 限制字段的字符数量
converters: nil,             #=> 
unconverted_fields: nil,
headers: false,              #=> 读取时忽略标题行,具体参考官方手册
return_headers: false,
write_headers: nil,
header_converters: nil,
skip_blanks: false,          #=> 忽略空行
force_quotes: false,         #=> 设置为true时,所有字段都将使用被包围
skip_lines: nil,             #=> 指定一个正则(str也会转换为正则),
                             #=> 匹配的行将被当作注释行而忽略
liberal_parsing: false,
internal_encoding: nil,
external_encoding: nil,
encoding: nil,
nil_value: nil,             #=> 使用此处设置的值替换所有nil字段
empty_value: "",            #=> 使用此处设置的值替换所有空字符串字段
quote_empty: true,          #=> 设置为false时,空字符串字段将转换为空字段
write_converters: nil,
write_nil_value: nil,      #=> 将以此处的值替换nil字段写入文件
write_empty_value: "",
strip: false

csv类方法处理csv数据

以csv格式写入文件

要向文件中写入csv格式的数据:

require 'csv'

writer = csv.open('/tmp/file.csv', 'w')
writer << ["junmajinlong", 29, 170, true]
writer << ["junma", 24, 176, false]
writer << ["jinlong", 25, 172, nil]
writer << ["majinlong", 23, 173, false]
writer.close

写入完成后,查看:

junmajinlong,29,170,true
junma,24,176,false
jinlong,25,172,
majinlong,23,173,false

注意其中的nil对应的写入内容为空。

可以直接在语句块中写入,这样的话可以自动关闭csv.open()打开的io流:

require 'csv'

csv.open('/tmp/file.csv', 'w') do |writer|
  writer << ["junmajinlong", 29, 170, true]
  writer << ["junma", 24, 176, false]
  writer << ["jinlong", 25, 172, nil]
  writer << ["majinlong", 23, 173, false]
end

csv.open()打开的是一个封装后的io流对象,它除了可以使用csv单独为其提供的一些方法(比如这里的<<)外,还可以使用很多io流对象的方法,比如seek()、tell()、flush()、eof?()、fsync()等等。

这里使用的<<方法是单独为其提供的,它涉及两个执行过程:

  • 将数组中各元素全部转换成字符串类型并使用逗号连接
  • 按行写入到csv打开的文件中

转换为csv格式的字符串

如果只是想执行第一个过程,即将数据转换成csv格式的字符串而不写入,可使用类方法generate_line()

p csv.generate_line ["junmajinlong", 29, 170, true]
p csv.generate_line ["jun ma", 24, 176, false]
p csv.generate_line ["jinlong", 25, 172, nil]
p csv.generate_line ["jin, long", 23, 173, false]
=begin
"junmajinlong,29,170,true\n"
"jun ma,24,176,false\n"
"jinlong,25,172,\n"
"\"jin, long\",23,173,false\n"
=end

从csv格式的文件中读数据

如果想要读取csv文件,可使用类方法read()或别名readlines():

pp csv.readlines('/tmp/file.csv')
=begin
[["junmajinlong", "29", "170", "true"],
 ["junma", "24", "176", "false"],
 ["jinlong", "25", "172", nil],
 ["majinlong", "23", "173", "false"]]
=end

注意:

  • 读取csv文件内容时,每行保存为一个数组,每个字段是这个数组中的一个元素
  • 读取csv文件内容时,除了不存在的字段转换为nil外,其它所有的数据都转换成了字符串类型。所以有时候可能需要去转换读取时的数据类型。关于类型转换,见后文

如果要按行读取csv文件的内容,使用类方法foreach():

csv.foreach('/tmp/file.csv') do |row|
  p row
end
=begin
["junmajinlong", "29", "170", "true"]
["junma", "24", "176", "false"]
["jinlong", "25", "172", nil]
["majinlong", "23", "173", "false"]
=end

从csv格式的字符串中读数据

如果想要从字符串中读取csv格式的数据,使用parse()和parse_line(),分别用于解析多行字符串和解析单行字符串(超出一行的自动被忽略)。

  • parse()不指定语句块时,返回包含解析每一行得到的数组,即一个数组的数组,它是一个csv table类型,有很多自己的方法
  • 指定语句块时,每一行对应的数组传递给语句块控制变量
str1=<<-eof
junmajinlong,29,170,true
jun ma,24,176,false
jinlong,25,172,
"jin, long",23,173,false
eof

# 不指定语句块时,parse返回数组
pp csv.parse str1
=begin
[["junmajinlong", "29", "170", "true"],
 ["jun ma", "24", "176", "false"],
 ["jinlong", "25", "172", nil],
 ["jin, long", "23", "173", "false"]]
=end

# 指定语句块时,parse将每行对应的数组传递给语句块
csv.parse(str1) {|row| p row}
=begin
["junmajinlong", "29", "170", "true"]
["jun ma", "24", "176", "false"]
["jinlong", "25", "172", nil]
["jin, long", "23", "173", "false"]
=end

str2="junmajinlong,29,170,true"
p csv.parse_line str2
["junmajinlong", "29", "170", "true"]

csv实例方法处理csv数据

  • csv.new()csv.open()可以创建csv对象(即一行一行csv格式的数据)
  • csv.generate()可将字符串转换成csv对象并将该对象传递给语句块
  • <<puts()add_row()可向csv目标中(字符串格式的csv或csv io流)写入行,它们是别名关系
  • gets()shift()readline()可从csv对象中读取一行数据
  • read()readlines()可以读取csv对象中的所有数据
  • each()可以从csv对象中迭代每一行
  • eof()eof?()可以判断是否读完所有数据
  • rewind()可以重置当前csv对象的偏移指针
  • line()可以获取最近一次读取的一行数据
  • lineno()可以获取当前已读取的行数
  • path()可以获取当前读取的csv文件名

csv table

csv.parse()、csv.read()、csv.table()等方法返回的都是数组的数组(二维数组),它们是csv table。

csv table按照表的方式来处理csv数据,比如关注于行、关注于字段的一些操作可以采用csv table相关的方法来处理。

# headers are part of data
data = csv.parse(<<~rows, headers: true)
  name,department,salary
  bob,engineering,1000
  jane,sales,2000
  john,management,5000
rows

data.class      #=> csv::table
data.first      #=> #<csv::row "name":"bob" "department":"engineering" "salary":"1000">
data.first.to_h #=> {"name"=>"bob", "department"=>"engineering", "salary"=>"1000"}

# headers provided by developer
data = csv.parse('bob,engineering,1000', headers: %i[name department salary])
data.first      #=> #<csv::row name:"bob" department:"engineering" salary:"1000">

csv字段类型转换

读取csv数据时,所有的数据都会转换为字符串格式。

# without any converters:
csv.parse('bob,2018-03-01,100')
#=> [["bob", "2018-03-01", "100"]]

可以在迭代每一行的语句块中对字段做必要的类型转换。

但如果类型转换方式比较简单,可以在读取数据时指定converters属性进行转换。该属性的值要么是csv的内置类型符号,要么是符号数组,要么是一个lambda表达式。有如下内置类型:

integer
float
numeric (float + integer)
date
datetime
all

当指定了类型转换后,每个字段将针对converters的值尝试做转换,转换失败则保留字段的值不变,所以如果通过lambda自定义类型转换时也一定要保证这一点。

csv.parse("1,2,3,4,5", converters: :numeric)
#=> [[1, 2, 3, 4, 5]]

# with built-in converters:
ct = csv.parse('bob,2018-03-01,100', converters: %i[numeric date])
#=> [["bob", #<date: 2018-03-01>, 100]]
ct.first[1] + 1  # 日期对象,加1天
#=> #<date: 2018-03-02 ((2458180j,0s,0n),+0s,2299161j)>

# with custom converters:
csv.parse('bob,2018-03-01,100', converters: [->(v) { time.parse(v) rescue v }])
#=> [["bob", 2018-03-01 00:00:00 +0200, "100"]]
(0)

相关文章:

  • Ruby正则表达式详解

    Ruby正则表达式详解

    ruby 正则表达式正则表达式是一种特殊序列的字符,它通过使用有专门语法的模式来匹配或查找字符串集合。正则表达式用事先定义好的一些特定字符、及这些特定字符的组合... [阅读全文]
  • 深入分析Ruby 变量

    深入分析Ruby 变量

    变量是持有可被任何程序使用的任何数据的存储位置。ruby 支持五种类型的变量。 一般小写字母、下划线开头:变量(variable)。 $开头:全局变量(gl... [阅读全文]
  • ruby中 %W{}和%w{}的使用案例详解

    ruby中 %W{}和%w{}的使用案例详解

    ruby中 %w{}和%w{}的使用%w{}是ruby中的一种快捷方式,用于创建一个以空格分隔的字符串数组。例如,%w{apple banana cherry}... [阅读全文]
  • Ruby 迭代器知识汇总

    Ruby 迭代器知识汇总

    简单来说:迭代(iterate)指的是重复做相同的事,所以迭代器(iterator)就是用来重复多次相同的事。迭代器是集合支持的方法。存储一组数据成员的对象称为... [阅读全文]
  • Ruby生成随机数的方法总结

    Ruby生成随机数的方法总结

    数字实际上不是随机的没有一台计算机能纯粹通过计算产生真正的随机数。它们能做的最好的事情就是生成伪随机数,伪随机数是一组看起来随机但实际上不是随机的数字。对于人类... [阅读全文]
  • 最新的CocoaPods安装教程

    最新的CocoaPods安装教程

    cocoapods是什么?当你开发ios应用时,会经常使用到很多第三方开源类库,比如jsonkit,afnetworking等等。可能某个类库又用到其他类库,所... [阅读全文]

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com