class CSV

Overview

Provides methods and classes for parsing and generating CSV (comma-separated values) strings.

This module conforms to RFC 4180.

Parsing

Several ways of parsing CSV are provided. The most straight-forward, but slow or inefficient for some scenarios, is CSV#parse, which returns an array of arrays of all data.

Rows can be traversed in a linear fashion with CSV#each_row, or using an Iterator.

To parse a CSV in an efficient way, optionally being able to access row values from header names, create an instance of a CSV.

Parsing with CSV#new

A CSV instance holds a cursor to the current row in the CSV. The cursor is advanced by invoking #next, which returns true if a next row was found, and false otherwise. A first call to #next is required to position the csv parser in the first row.

Once positioned in a row, values can be obtained with the several #[] methods, which can accept a header name, column position, or header name pattern as a Regex.

Additionally, a Row object can be obtained with the #row method which provides similar methods and can be converted to an Array or Hash.

Example

require "csv"

csv = CSV.new("Name, Age\nJohn, 20\nPeter, 30", headers: true)
csv.next # => true

csv["Name"]  # => "John"
csv[0]       # => "John"
csv[-2]      # => "John"
csv[/name/i] # => "John"

csv["Age"] # => " 20"

csv.row.to_a # => ["John", " 20"]
csv.row.to_h # => {"Name" => "John", "Age" => " 20"}

csv.next    # => true
csv["Name"] # => "Peter"

csv.next # => false

Building

To create CSV data, check CSV#build and the CSV::Builder class.

Defined in:

csv.cr
csv/error.cr

Constant Summary

DEFAULT_QUOTE_CHAR = '"'
DEFAULT_SEPARATOR = ','

Class Method Summary

Instance Method Summary

Instance methods inherited from class Reference

==(other)
==(other : self)
==
, dup dup, hash hash, inspect(io : IO) : Nil inspect, object_id : UInt64 object_id, same?(other : Reference)
same?(other : Nil)
same?
, to_s(io : IO) : Nil to_s

Instance methods inherited from class Object

!=(other) !=, !~(other) !~, ==(other) ==, ===(other)
===(other : YAML::Any)
===(other : JSON::Any)
===
, =~(other) =~, class class, crystal_type_id crystal_type_id, dup dup, hash hash, inspect(io : IO)
inspect
inspect
, itself itself, not_nil! not_nil!, tap(&block) tap, to_json to_json, to_pretty_json(indent : String = " ")
to_pretty_json(io : IO, indent : String = " ")
to_pretty_json
, to_s
to_s(io : IO)
to_s
, to_yaml
to_yaml(io : IO)
to_yaml
, try(&block) try

Class methods inherited from class Object

==(other : Class) ==, ===(other) ===, cast(other) : self cast, clone clone, dup dup, from_json(string_or_io) : self
from_json(string_or_io, root : String) : self
from_json
, from_yaml(string : String) : self from_yaml, hash hash, inspect(io) inspect, name : String name, nilable? nilable?, to_s(io) to_s, |(other : U.class) forall U |

Class Method Detail

def self.build(io : IO, &block) #

Appends CSV data to the given IO. This yields a CSV::Builder that writes to the given IO.

io = MemoryIO.new
io.puts "HEADER"
CSV.build(io) do |csv|
  csv.row "one", "two"
  csv.row "three"
end
io.to_s # => "HEADER\none,two\nthree"

[View source]
def self.build(&block) : String #

Builds a CSV. This yields a CSV::Builder to the given block.

result = CSV.build do |csv|
  csv.row "one", "two"
  csv.row "three"
end
result # => "one,two\nthree"

[View source]
def self.each_row(string_or_io : String | IO, separator : Char = DEFAULT_SEPARATOR, quote_char : Char = DEFAULT_QUOTE_CHAR, &block) #

Yields each of a CSV's rows as an Array(String). see CSV.parse about the separator and quote_char arguments

CSV.each_row("one,two\nthree") do |row|
  puts row
end

Output:

["one", "two"]
["three"]

[View source]
def self.each_row(string_or_io : String | IO, separator : Char = DEFAULT_SEPARATOR, quote_char : Char = DEFAULT_QUOTE_CHAR) #

Returns an Iterator of Array(String) over a CSV's rows. see CSV.parse about the separator and quote_char arguments

rows = CSV.each_row("one,two\nthree")
rows.next # => ["one", "two"]
rows.next # => ["three"]

[View source]
def self.new(string_or_io : String | IO, headers = false, strip = false, separator : Char = DEFAULT_SEPARATOR, quote_char : Char = DEFAULT_QUOTE_CHAR) #

Creates a new instance from the given String or IO.

If strip is true, row values are stripped with String#strip before being returned from methods.

If headers is true, row values can be accessed with header names or patterns. Headers are always stripped.

see CSV.parse about the separator and quote_char arguments


[View source]
def self.new(string_or_io : String | IO, headers = false, strip = false, separator : Char = DEFAULT_SEPARATOR, quote_char : Char = DEFAULT_QUOTE_CHAR, &block) #

Creates a new instance from the given String or IO, and yields it to the given block once for each row in the CSV.

If strip is true, row values are stripped with String#strip before being returned from methods.

If headers is true, row values can be accessed with header names or patterns. Headers are always stripped.

see CSV.parse about the separator and quote_char arguments


[View source]
def self.parse(string_or_io : String | IO, separator : Char = DEFAULT_SEPARATOR, quote_char : Char = DEFAULT_QUOTE_CHAR) : Array(Array(String)) #

Parses a CSV or IO into an array. takes optional separator and quote_char arguments for defining non-standard csv cell separators and quote characters

CSV.parse("one,two\nthree")
# => [["one", "two"], ["three"]]
CSV.parse("one;two\n'three;'", separator: ';', quote_char: '\'')
# => [["one", "two"], ["three;"]]

[View source]

Instance Method Detail

def [](header : String) : String #

Returns the current row's value corresponding to the given header name. Raises KeyError if no such header exists. Raises CSV::Error if headers were not requested.


[View source]
def [](column : Int) : String #

Returns the current row's value at the given column index. A negative index counts from the end. Raises IndexError if no such column exists.


[View source]
def [](header_pattern : Regex) : String #

Returns the current row's value corresponding to the given header_pattern. Raises KeyError if no such header exists. Raises CSV::Error if headers were not requested.


[View source]
def []?(header : String) : String | Nil #

Returns the current row's value corresponding to the given header name. Returns nil if no such header exists. Raises CSV::Error if headers were not requested.


[View source]
def []?(column : Int) : String | Nil #

Returns the current row's value at the given column index. A negative index counts from the end. Returns nil if no such column exists.


[View source]
def []?(header_pattern : Regex) : String | Nil #

Returns the current row's value corresponding to the given header_pattern. Returns nil if no such header exists. Raises CSV::Error if headers were not requested.


[View source]
def each(&block) #

Invokes the block once for each row in this CSV, yielding self.


[View source]
def headers : Array(String) #

Returns this CSV headers. Their values are always stripped. Raises CSV::Error if headers were not requested.


[View source]
def next #

Advanced the cursor to the next row. Must be called once to position the cursor in the first row. Returns true if a next row was found, false otherwise.


[View source]
def row : Row #

Returns the current row as a Row instance.


[View source]