class CSV

Overview

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

This module conforms toRFC 4180.

NOTE To useCSV or its children, you must explicitly import it withrequire "csv"

Parsing

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

Rows can be traversed in a linear fashion withCSV#each_row, or using anIterator.

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

Parsing withCSV#new

A CSV instance holds a cursor to the current row in the CSV. The cursor is advanced by invoking#next, which returnstrue if a next row was found, andfalse 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 aRegex.

Additionally, aRow object can be obtained with the#row method which provides similar methods and can be converted to anArray orHash.

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, checkCSV#build and theCSV::Builder class.

Defined in:

csv.cr
csv/error.cr

Constant Summary

DEFAULT_QUOTE_CHAR = '"'
DEFAULT_SEPARATOR = ','

Constructors

Class Method Summary

Instance Method Summary

Instance methods inherited from class Reference

==(other : self)
==(other : JSON::Any)
==(other : YAML::Any)
==(other)
==
, dup dup, hash(hasher) hash, initialize initialize, inspect(io : IO) : Nil inspect, object_id : UInt64 object_id, pretty_print(pp) : Nil pretty_print, same?(other : Reference) : Bool
same?(other : Nil)
same?
, to_s(io : IO) : Nil to_s

Constructor methods inherited from class Reference

new new, unsafe_construct(address : Pointer, *args, **opts) : self unsafe_construct

Class methods inherited from class Reference

pre_initialize(address : Pointer) pre_initialize

Instance methods inherited from class Object

! : Bool !, !=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other)
===
, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash
hash
, in?(collection : Object) : Bool
in?(*values : Object) : Bool
in?
, inspect(io : IO) : Nil
inspect : String
inspect
, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil!
not_nil!
, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String
to_json
, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil
to_pretty_json
, to_s(io : IO) : Nil
to_s : String
to_s
, to_yaml(io : IO) : Nil
to_yaml : String
to_yaml
, try(&) try, unsafe_as(type : T.class) forall T unsafe_as

Class methods inherited from class Object

from_json(string_or_io : String | IO, root : String)
from_json(string_or_io : String | IO)
from_json
, from_yaml(string_or_io : String | IO) from_yaml

Macros inherited from class Object

class_getter(*names, &block) class_getter, class_getter!(*names) class_getter!, class_getter?(*names, &block) class_getter?, class_property(*names, &block) class_property, class_property!(*names) class_property!, class_property?(*names, &block) class_property?, class_setter(*names) class_setter, def_clone def_clone, def_equals(*fields) def_equals, def_equals_and_hash(*fields) def_equals_and_hash, def_hash(*fields) def_hash, delegate(*methods, to object) delegate, forward_missing_to(delegate) forward_missing_to, getter(*names, &block) getter, getter!(*names) getter!, getter?(*names, &block) getter?, property(*names, &block) property, property!(*names) property!, property?(*names, &block) property?, setter(*names) setter

Constructor Detail

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

Creates a new instance from the givenString orIO.

  • Ifstrip istrue, row values are stripped withString#strip before being returned from methods.
  • Ifheaders istrue, row values can be accessed with header names or patterns. Headers are always stripped.

SeeCSV.parse about theseparator andquote_char arguments.


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 givenString orIO, and yields it to the given block once for each row in the CSV.

  • Ifstrip istrue, row values are stripped withString#strip before being returned from methods.
  • Ifheaders istrue, row values can be accessed with header names or patterns. Headers are always stripped.

SeeCSV.parse about theseparator andquote_char arguments.


Class Method Detail

def self.build(separator : Char = DEFAULT_SEPARATOR, quote_char : Char = DEFAULT_QUOTE_CHAR, quoting : Builder::Quoting = Builder::Quoting::RFC, &) : String #

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

Takes optionalquoting argument to define quote behavior.

require "csv"

result = CSV.build do |csv|
  csv.row "one", "two"
  csv.row "three"
end
result # => "one,two\nthree\n"
result = CSV.build(quoting: CSV::Builder::Quoting::ALL) do |csv|
  csv.row "one", "two"
  csv.row "three"
end
result # => "\"one\",\"two\"\n\"three\"\n"

See:CSV::Builder::Quoting


def self.build(io : IO, separator : Char = DEFAULT_SEPARATOR, quote_char : Char = DEFAULT_QUOTE_CHAR, quoting : Builder::Quoting = Builder::Quoting::RFC, &) : Nil #

Appends CSV data to the givenIO. This yields aCSV::Builder that writes to the givenIO.

require "csv"

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

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

Yields each of a CSV's rows as anArray(String).

SeeCSV.parse about theseparator andquote_char arguments.

require "csv"

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

Output:

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

def self.each_row(string_or_io : String | IO, separator : Char = DEFAULT_SEPARATOR, quote_char : Char = DEFAULT_QUOTE_CHAR) : Iterator(Array(String)) #

Returns anIterator ofArray(String) over a CSV's rows.

SeeCSV.parse about theseparator andquote_char arguments.

require "csv"

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

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

Parses a CSV orIO into an array.

Takes optionalseparator andquote_char arguments for defining non-standard csv cell separators and quote characters.

require "csv"

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

Instance Method Detail

def [](header : String) : String #

Returns the current row's value corresponding to the givenheader name. RaisesKeyError if no such header exists. RaisesCSV::Error if headers were not requested.


def [](column : Int) : String #

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


def [](header_pattern : Regex, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : String #

Returns the current row's value corresponding to the givenheader_pattern. RaisesKeyError if no such header exists. RaisesCSV::Error if headers were not requested.


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

Returns the current row's value corresponding to the givenheader name. Returnsnil if no such header exists. RaisesCSV::Error if headers were not requested.


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

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


def []?(header_pattern : Regex, *, options : Regex::MatchOptions = Regex::MatchOptions::None) : String | Nil #

Returns the current row's value corresponding to the givenheader_pattern. Returnsnil if no such header exists. RaisesCSV::Error if headers were not requested.


def each(&) : Nil #

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


def headers : Array(String) #

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


def next : Bool #

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


def rewind : Nil #

Rewinds this CSV to the beginning, rewinding the underlying IO if any.


def row : Row #

Returns the current row as aRow instance.


def values_at(*columns : Int) #

Returns a tuple of the current row's values at given indices A negative index counts from the end. RaisesIndexError if any column doesn't exist The behavior of returning a tuple is similar toHash#values_at


def values_at(*headers : String) #

Returns a tuple of the current row's values corresponding to the givenheaders RaisesKeyError if any header doesn't exist. RaisesCSV::Error if headers were not requested The behavior of returning a tuple is similar toHash#values_at