Class: CSV
- Inherits:
-
Object
- Object
- CSV
- Extended by:
- Forwardable
- Includes:
- Enumerable
- Defined in:
- lib/csv.rb,
lib/csv/row.rb,
lib/csv/table.rb,
lib/csv/parser.rb,
lib/csv/writer.rb,
lib/csv/match_p.rb,
lib/csv/version.rb,
lib/csv/delete_suffix.rb,
lib/csv/fields_converter.rb
Overview
CSV
CSV (comma-separated variables) data is a text representation of a table:
-
A row separator delimits table rows. A common row separator is the newline character
"\n". -
A column separator delimits fields in a row. A common column separator is the comma character
",".
This CSV String, with row separator "\n" and column separator ",", has three rows and two columns:
"foo,0\nbar,1\nbaz,2\n"
Despite the name CSV, a CSV representation can use different separators.
Class CSV
Class CSV provides methods for:
-
Parsing CSV data from a String object, a File (via its file path), or an IO object.
-
Generating CSV data to a String object.
To make CSV available:
require 'csv'
All examples here assume that this has been done.
Keeping It Simple
A CSV object has dozens of instance methods that offer fine-grained control of parsing and generating CSV data. For many needs, though, simpler approaches will do.
This section summarizes the singleton methods in CSV that allow you to parse and generate without explicitly creating CSV objects. For details, follow the links.
Simple Parsing
Parsing methods commonly return either of:
-
An Array of Arrays of Strings:
-
The outer Array is the entire “table”.
-
Each inner Array is a row.
-
Each String is a field.
-
-
A CSV::Table object. For details, see CSV with Headers.
Parsing a String
The input to be parsed can be a string:
string = "foo,0\nbar,1\nbaz,2\n"
Method CSV.parse returns the entire CSV data:
CSV.parse(string) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
Method CSV.parse_line returns only the first row:
CSV.parse_line(string) # => ["foo", "0"]
CSV extends class String with instance method String#parse_csv, which also returns only the first row:
string.parse_csv # => ["foo", "0"]
Parsing Via a File Path
The input to be parsed can be in a file:
string = "foo,0\nbar,1\nbaz,2\n"
path = 't.csv'
File.write(path, string)
Method CSV.read returns the entire CSV data:
CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
Method CSV.foreach iterates, passing each row to the given block:
CSV.foreach(path) do |row|
p row
end
Output:
["foo", "0"]
["bar", "1"]
["baz", "2"]
Method CSV.table returns the entire CSV data as a CSV::Table object:
CSV.table(path) # => #<CSV::Table mode:col_or_row row_count:3>
Parsing from an Open IO Stream
The input to be parsed can be in an open IO stream:
Method CSV.read returns the entire CSV data:
File.open(path) do |file|
CSV.read(file)
end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
As does method CSV.parse:
File.open(path) do |file|
CSV.parse(file)
end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
Method CSV.parse_line returns only the first row:
File.open(path) do |file|
CSV.parse_line(file)
end # => ["foo", "0"]
Method CSV.foreach iterates, passing each row to the given block:
File.open(path) do |file|
CSV.foreach(file) do |row|
p row
end
end
Output:
["foo", "0"]
["bar", "1"]
["baz", "2"]
Method CSV.table returns the entire CSV data as a CSV::Table object:
File.open(path) do |file|
CSV.table(file)
end # => #<CSV::Table mode:col_or_row row_count:3>
Simple Generating
Method CSV.generate returns a String; this example uses method CSV#<< to append the rows that are to be generated:
output_string = CSV.generate do |csv|
csv << ['foo', 0]
csv << ['bar', 1]
csv << ['baz', 2]
end
output_string # => "foo,0\nbar,1\nbaz,2\n"
Method CSV.generate_line returns a String containing the single row constructed from an Array:
CSV.generate_line(['foo', '0']) # => "foo,0\n"
CSV extends class Array with instance method Array#to_csv, which forms an Array into a String:
['foo', '0'].to_csv # => "foo,0\n"
“Filtering” CSV
Method CSV.filter provides a Unix-style filter for CSV data. The input data is processed to form the output data:
in_string = "foo,0\nbar,1\nbaz,2\n"
out_string = ''
CSV.filter(in_string, out_string) do |row|
row[0] = row[0].upcase
row[1] *= 4
end
out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n"
CSV Objects
There are three ways to create a CSV object:
-
Method CSV.new returns a new CSV object.
-
Method CSV.instance returns a new or cached CSV object.
-
Method CSV() also returns a new or cached CSV object.
Instance Methods
CSV has three groups of instance methods:
-
Its own internally defined instance methods.
-
Methods included by module Enumerable.
-
Methods delegated to class IO. See below.
Delegated Methods
For convenience, a CSV object will delegate to many methods in class IO. (A few have wrapper “guard code” in CSV.) You may call:
-
IO#binmode
-
#binmode?
-
IO#close
-
IO#close_read
-
IO#close_write
-
IO#closed?
-
#eof
-
#eof?
-
IO#external_encoding
-
IO#fcntl
-
IO#fileno
-
#flock
-
IO#flush
-
IO#fsync
-
IO#internal_encoding
-
#ioctl
-
IO#isatty
-
#path
-
IO#pid
-
IO#pos
-
IO#pos=
-
IO#reopen
-
#rewind
-
IO#seek
-
#stat
-
IO#string
-
IO#sync
-
IO#sync=
-
IO#tell
-
#to_i
-
#to_io
-
IO#truncate
-
IO#tty?
Options
The default values for options are:
DEFAULT_OPTIONS = {
# For both parsing and generating.
col_sep: ",",
row_sep: :auto,
quote_char: '"',
# For parsing.
field_size_limit: nil,
converters: nil,
unconverted_fields: nil,
headers: false,
return_headers: false,
header_converters: nil,
skip_blanks: false,
skip_lines: nil,
liberal_parsing: false,
nil_value: nil,
empty_value: "",
# For generating.
write_headers: nil,
quote_empty: true,
force_quotes: false,
write_converters: nil,
write_nil_value: nil,
write_empty_value: "",
strip: false,
}
Options for Parsing
Options for parsing, described in detail below, include:
-
row_sep: Specifies the row separator; used to delimit rows. -
col_sep: Specifies the column separator; used to delimit fields. -
quote_char: Specifies the quote character; used to quote fields. -
field_size_limit: Specifies the maximum field size allowed. -
converters: Specifies the field converters to be used. -
unconverted_fields: Specifies whether unconverted fields are to be available. -
headers: Specifies whether data contains headers, or specifies the headers themselves. -
return_headers: Specifies whether headers are to be returned. -
header_converters: Specifies the header converters to be used. -
skip_blanks: Specifies whether blanks lines are to be ignored. -
skip_lines: Specifies how comments lines are to be recognized. -
strip: Specifies whether leading and trailing whitespace are to be stripped from fields.. -
liberal_parsing: Specifies whether CSV should attempt to parse non-compliant data. -
nil_value: Specifies the object that is to be substituted for each null (no-text) field. -
empty_value: Specifies the object that is to be substituted for each empty field.
:include: ../doc/options/common/row_sep.rdoc
:include: ../doc/options/common/col_sep.rdoc
:include: ../doc/options/common/quote_char.rdoc
:include: ../doc/options/parsing/field_size_limit.rdoc
:include: ../doc/options/parsing/converters.rdoc
:include: ../doc/options/parsing/unconverted_fields.rdoc
:include: ../doc/options/parsing/headers.rdoc
:include: ../doc/options/parsing/return_headers.rdoc
:include: ../doc/options/parsing/header_converters.rdoc
:include: ../doc/options/parsing/skip_blanks.rdoc
:include: ../doc/options/parsing/skip_lines.rdoc
:include: ../doc/options/parsing/strip.rdoc
:include: ../doc/options/parsing/liberal_parsing.rdoc
:include: ../doc/options/parsing/nil_value.rdoc
:include: ../doc/options/parsing/empty_value.rdoc
Options for Generating
Options for generating, described in detail below, include:
-
row_sep: Specifies the row separator; used to delimit rows. -
col_sep: Specifies the column separator; used to delimit fields. -
quote_char: Specifies the quote character; used to quote fields. -
write_headers: Specifies whether headers are to be written. -
force_quotes: Specifies whether each output field is to be quoted. -
quote_empty: Specifies whether each empty output field is to be quoted. -
write_converters: Specifies the field converters to be used in writing. -
write_nil_value: Specifies the object that is to be substituted for eachnil-valued field. -
write_empty_value: Specifies the object that is to be substituted for each empty field.
:include: ../doc/options/common/row_sep.rdoc
:include: ../doc/options/common/col_sep.rdoc
:include: ../doc/options/common/quote_char.rdoc
:include: ../doc/options/generating/write_headers.rdoc
:include: ../doc/options/generating/force_quotes.rdoc
:include: ../doc/options/generating/quote_empty.rdoc
:include: ../doc/options/generating/write_converters.rdoc
:include: ../doc/options/generating/write_nil_value.rdoc
:include: ../doc/options/generating/write_empty_value.rdoc
CSV with Headers
CSV allows to specify column names of CSV file, whether they are in data, or provided separately. If headers are specified, reading methods return an instance of CSV::Table, consisting of CSV::Row.
# 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">
Converters
By default, each value (field or header) parsed by CSV is formed into a String. You can use a field converter or header converter to intercept and modify the parsed values:
-
See Field Converters.
-
See Header Converters.
Also by default, each value to be written during generation is written ‘as-is’. You can use a write converter to modify values before writing.
-
See Write Converters.
Specifying Converters
You can specify converters for parsing or generating in the options argument to various CSV methods:
-
Option
convertersfor converting parsed field values. -
Option
header_convertersfor converting parsed header values. -
Option
write_convertersfor converting values to be written (generated).
There are three forms for specifying converters:
-
A converter proc: executable code to be used for conversion.
-
A converter name: the name of a stored converter.
-
A converter list: an array of converter procs, converter names, and converter lists.
Converter Procs
This converter proc, strip_converter, accepts a value field and returns field.strip:
strip_converter = proc {|field| field.strip }
In this call to CSV.parse, the keyword argument converters: string_converter specifies that:
-
Proc
string_converteris to be called for each parsed field. -
The converter’s return value is to replace the
fieldvalue.
Example:
string = " foo , 0 \n bar , 1 \n baz , 2 \n"
array = CSV.parse(string, converters: strip_converter)
array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
A converter proc can receive a second argument, field_info, that contains details about the field. This modified strip_converter displays its arguments:
strip_converter = proc do |field, field_info|
p [field, field_info]
field.strip
end
string = " foo , 0 \n bar , 1 \n baz , 2 \n"
array = CSV.parse(string, converters: strip_converter)
array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
Output:
[" foo ", #<struct CSV::FieldInfo index=0, line=1, header=nil>]
[" 0 ", #<struct CSV::FieldInfo index=1, line=1, header=nil>]
[" bar ", #<struct CSV::FieldInfo index=0, line=2, header=nil>]
[" 1 ", #<struct CSV::FieldInfo index=1, line=2, header=nil>]
[" baz ", #<struct CSV::FieldInfo index=0, line=3, header=nil>]
[" 2 ", #<struct CSV::FieldInfo index=1, line=3, header=nil>]
Each CSV::Info object shows:
-
The 0-based field index.
-
The 1-based line index.
-
The field header, if any.
Stored Converters
A converter may be given a name and stored in a structure where the parsing methods can find it by name.
The storage structure for field converters is the Hash CSV::Converters. It has several built-in converter procs:
-
:integer: converts each String-embedded integer into a true Integer. -
:float: converts each String-embedded float into a true Float. -
:date: converts each String-embedded date into a true Date. -
:date_time: converts each String-embedded date-time into a true DateTime
. This example creates a converter proc, then stores it:
strip_converter = proc {|field| field.strip }
CSV::Converters[:strip] = strip_converter
Then the parsing method call can refer to the converter by its name, :strip:
string = " foo , 0 \n bar , 1 \n baz , 2 \n"
array = CSV.parse(string, converters: :strip)
array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
The storage structure for header converters is the Hash CSV::HeaderConverters, which works in the same way. It also has built-in converter procs:
-
:downcase: Downcases each header. -
:symbol: Converts each header to a Symbol.
There is no such storage structure for write headers.
Converter Lists
A converter list is an Array that may include any assortment of:
-
Converter procs.
-
Names of stored converters.
-
Nested converter lists.
Examples:
numeric_converters = [:integer, :float]
date_converters = [:date, :date_time]
[numeric_converters, strip_converter]
[strip_converter, date_converters, :float]
Like a converter proc, a converter list may be named and stored in either CSV::Converters or CSV::HeaderConverters:
CSV::Converters[:custom] = [strip_converter, date_converters, :float]
CSV::HeaderConverters[:custom] = [:downcase, :symbol]
There are two built-in converter lists:
CSV::Converters[:numeric] # => [:integer, :float]
CSV::Converters[:all] # => [:date_time, :numeric]
Field Converters
With no conversion, all parsed fields in all rows become Strings:
string = "foo,0\nbar,1\nbaz,2\n"
ary = CSV.parse(string)
ary # => # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
When you specify a field converter, each parsed field is passed to the converter; its return value becomes the stored value for the field. A converter might, for example, convert an integer embedded in a String into a true Integer. (In fact, that’s what built-in field converter :integer does.)
There are three ways to use field converters.
-
Using option converters with a parsing method:
ary = CSV.parse(string, converters: :integer) ary # => [0, 1, 2] # => [["foo", 0], ["bar", 1], ["baz", 2]] -
Using option converters with a new CSV instance:
csv = CSV.new(string, converters: :integer) # Field converters in effect: csv.converters # => [:integer] csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]] -
Using method #convert to add a field converter to a CSV instance:
csv = CSV.new(string) # Add a converter. csv.convert(:integer) csv.converters # => [:integer] csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]]
Installing a field converter does not affect already-read rows:
csv = CSV.new(string)
csv.shift # => ["foo", "0"]
# Add a converter.
csv.convert(:integer)
csv.converters # => [:integer]
csv.read # => [["bar", 1], ["baz", 2]]
There are additional built-in converters, and custom converters are also supported.
Built-In Field Converters
The built-in field converters are in Hash CSV::Converters:
-
Each key is a field converter name.
-
Each value is one of:
-
A Proc field converter.
-
An Array of field converter names.
-
Display:
CSV::Converters.each_pair do |name, value|
if value.kind_of?(Proc)
p [name, value.class]
else
p [name, value]
end
end
Output:
[:integer, Proc]
[:float, Proc]
[:numeric, [:integer, :float]]
[:date, Proc]
[:date_time, Proc]
[:all, [:date_time, :numeric]]
Each of these converters transcodes values to UTF-8 before attempting conversion. If a value cannot be transcoded to UTF-8 the conversion will fail and the value will remain unconverted.
Converter :integer converts each field that Integer() accepts:
data = '0,1,2,x'
# Without the converter
csv = CSV.parse_line(data)
csv # => ["0", "1", "2", "x"]
# With the converter
csv = CSV.parse_line(data, converters: :integer)
csv # => [0, 1, 2, "x"]
Converter :float converts each field that Float() accepts:
data = '1.0,3.14159,x'
# Without the converter
csv = CSV.parse_line(data)
csv # => ["1.0", "3.14159", "x"]
# With the converter
csv = CSV.parse_line(data, converters: :float)
csv # => [1.0, 3.14159, "x"]
Converter :numeric converts with both :integer and :float..
Converter :date converts each field that Date::parse accepts:
data = '2001-02-03,x'
# Without the converter
csv = CSV.parse_line(data)
csv # => ["2001-02-03", "x"]
# With the converter
csv = CSV.parse_line(data, converters: :date)
csv # => [#<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>, "x"]
Converter :date_time converts each field that DateTime::parse accepts:
data = '2020-05-07T14:59:00-05:00,x'
# Without the converter
csv = CSV.parse_line(data)
csv # => ["2020-05-07T14:59:00-05:00", "x"]
# With the converter
csv = CSV.parse_line(data, converters: :date_time)
csv # => [#<DateTime: 2020-05-07T14:59:00-05:00 ((2458977j,71940s,0n),-18000s,2299161j)>, "x"]
Converter :numeric converts with both :date_time and :numeric..
As seen above, method #convert adds converters to a CSV instance, and method #converters returns an Array of the converters in effect:
csv = CSV.new('0,1,2')
csv.converters # => []
csv.convert(:integer)
csv.converters # => [:integer]
csv.convert(:date)
csv.converters # => [:integer, :date]
Custom Field Converters
You can define a custom field converter:
strip_converter = proc {|field| field.strip }
Add it to the Converters Hash:
CSV::Converters[:strip] = strip_converter
Use it by name:
string = " foo , 0 \n bar , 1 \n baz , 2 \n"
array = CSV.parse(string, converters: strip_converter)
array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
Header Converters
Header converters operate only on headers (and not on other rows).
There are three ways to use header converters; these examples use built-in header converter :dowhcase, which downcases each parsed header.
-
Option
header_converterswith a singleton parsing method:string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2" tbl = CSV.parse(string, headers: true, header_converters: :downcase) tbl.class # => CSV::Table tbl.headers # => ["name", "count"] -
Option
header_converterswith a new CSV instance:csv = CSV.new(string, header_converters: :downcase) # Header converters in effect: csv.header_converters # => [:downcase] tbl = CSV.parse(string, headers: true) tbl.headers # => ["Name", "Count"] -
Method #header_convert adds a header converter to a CSV instance:
csv = CSV.new(string) # Add a header converter. csv.header_convert(:downcase) csv.header_converters # => [:downcase] tbl = CSV.parse(string, headers: true) tbl.headers # => ["Name", "Count"]
Built-In Header Converters
The built-in header converters are in Hash CSV::HeaderConverters. The keys there are the names of the converters:
CSV::HeaderConverters.keys # => [:downcase, :symbol]
Converter :downcase converts each header by downcasing it:
string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
tbl = CSV.parse(string, headers: true, header_converters: :downcase)
tbl.class # => CSV::Table
tbl.headers # => ["name", "count"]
Converter :symbol converts each header by making it into a Symbol:
string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2"
tbl = CSV.parse(string, headers: true, header_converters: :symbol)
tbl.headers # => [:name, :count]
Details:
-
Strips leading and trailing whitespace.
-
Downcases the header.
-
Replaces embedded spaces with underscores.
-
Removes non-word characters.
-
Makes the string into a Symbol.
Custom Header Converters
You can define a custom header converter:
upcase_converter = proc {|header| header.upcase }
Add it to the HeaderConverters Hash:
CSV::HeaderConverters[:upcase] = upcase_converter
Use it by name:
string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
table = CSV.parse(string, headers: true, converters: upcase_converter)
table # => #<CSV::Table mode:col_or_row row_count:4>
table.headers # => ["Name", "Value"]
Write Converters
When you specify a write converter for generating CSV, each field to be written is passed to the converter; its return value becomes the new value for the field. A converter might, for example, strip whitespace from a field.
-
Using no write converter (all fields unmodified):
output_string = CSV.generate do |csv| csv << [' foo ', 0] csv << [' bar ', 1] csv << [' baz ', 2] end output_string # => " foo ,0\n bar ,1\n baz ,2\n" -
Using option
write_converters:strip_converter = proc {|field| field.respond_to?(:strip) ? field.strip : field } upcase_converter = proc {|field| field.respond_to?(:upcase) ? field.upcase : field } converters = [strip_converter, upcase_converter] output_string = CSV.generate(write_converters: converters) do |csv| csv << [' foo ', 0] csv << [' bar ', 1] csv << [' baz ', 2] end output_string # => "FOO,0\nBAR,1\nBAZ,2\n"
Character Encodings (M17n or Multilingualization)
This new CSV parser is m17n savvy. The parser works in the Encoding of the IO or String object being read from or written to. Your data is never transcoded (unless you ask Ruby to transcode it for you) and will literally be parsed in the Encoding it is in. Thus CSV will return Arrays or Rows of Strings in the Encoding of your data. This is accomplished by transcoding the parser itself into your Encoding.
Some transcoding must take place, of course, to accomplish this multiencoding support. For example, :col_sep, :row_sep, and :quote_char must be transcoded to match your data. Hopefully this makes the entire process feel transparent, since CSV’s defaults should just magically work for your data. However, you can set these values manually in the target Encoding to avoid the translation.
It’s also important to note that while all of CSV’s core parser is now Encoding agnostic, some features are not. For example, the built-in converters will try to transcode data to UTF-8 before making conversions. Again, you can provide custom converters that are aware of your Encodings to avoid this translation. It’s just too hard for me to support native conversions in all of Ruby’s Encodings.
Anyway, the practical side of this is simple: make sure IO and String objects passed into CSV have the proper Encoding set and everything should just work. CSV methods that allow you to open IO objects (CSV::foreach(), CSV::open(), CSV::read(), and CSV::readlines()) do allow you to specify the Encoding.
One minor exception comes when generating CSV into a String with an Encoding that is not ASCII compatible. There’s no existing data for CSV to use to prepare itself and thus you will probably need to manually specify the desired Encoding for most of those cases. It will try to guess using the fields in a row of output though, when using CSV::generate_line() or Array#to_csv().
I try to point out any other Encoding issues in the documentation of methods as they come up.
This has been tested to the best of my ability with all non-“dummy” Encodings Ruby ships with. However, it is brave new code and may have some bugs. Please feel free to report any issues you find with it.
Defined Under Namespace
Modules: DeleteSuffix, MatchP Classes: FieldInfo, FieldsConverter, MalformedCSVError, Parser, Row, Table, Writer
Constant Summary collapse
- DateMatcher =
A Regexp used to find and convert some common Date formats.
/ \A(?: (\w+,?\s+)?\w+\s+\d{1,2},?\s+\d{2,4} | \d{4}-\d{2}-\d{2} )\z /x- DateTimeMatcher =
A Regexp used to find and convert some common DateTime formats.
/ \A(?: (\w+,?\s+)?\w+\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2},?\s+\d{2,4} | \d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2} | # ISO-8601 \d{4}-\d{2}-\d{2} (?:T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?(?:[+-]\d{2}(?::\d{2})|Z)?)?)? )\z /x- ConverterEncoding =
The encoding used by all converters.
Encoding.find("UTF-8")
- Converters =
A Hash containing the names and Procs for the built-in field converters. See Built-In Field Converters.
This Hash is intentionally left unfrozen, and may be extended with custom field converters. See Custom Field Converters.
{ integer: lambda { |f| Integer(f.encode(ConverterEncoding)) rescue f }, float: lambda { |f| Float(f.encode(ConverterEncoding)) rescue f }, numeric: [:integer, :float], date: lambda { |f| begin e = f.encode(ConverterEncoding) e.match?(DateMatcher) ? Date.parse(e) : f rescue # encoding conversion or date parse errors f end }, date_time: lambda { |f| begin e = f.encode(ConverterEncoding) e.match?(DateTimeMatcher) ? DateTime.parse(e) : f rescue # encoding conversion or date parse errors f end }, all: [:date_time, :numeric], }
- HeaderConverters =
A Hash containing the names and Procs for the built-in header converters. See Built-In Header Converters.
This Hash is intentionally left unfrozen, and may be extended with custom field converters. See Custom Header Converters.
{ downcase: lambda { |h| h.encode(ConverterEncoding).downcase }, symbol: lambda { |h| h.encode(ConverterEncoding).downcase.gsub(/[^\s\w]+/, "").strip. gsub(/\s+/, "_").to_sym } }
- DEFAULT_OPTIONS =
Default values for method options.
{ # For both parsing and generating. col_sep: ",", row_sep: :auto, quote_char: '"', # For parsing. field_size_limit: nil, converters: nil, unconverted_fields: nil, headers: false, return_headers: false, header_converters: nil, skip_blanks: false, skip_lines: nil, liberal_parsing: false, nil_value: nil, empty_value: "", # For generating. write_headers: nil, quote_empty: true, force_quotes: false, write_converters: nil, write_nil_value: nil, write_empty_value: "", strip: false, }.freeze
- VERSION =
The version of the installed library.
"3.1.6"
Instance Attribute Summary collapse
-
#encoding ⇒ Object
readonly
:call-seq: csv.encoding -> endcoding.
Class Method Summary collapse
-
.filter(input = nil, output = nil, **options) ⇒ Object
:call-seq: filter(**options) {|row| … } filter(in_string, **options) {|row| … } filter(in_io, **options) {|row| … } filter(in_string, out_string, **options) {|row| … } filter(in_string, out_io, **options) {|row| … } filter(in_io, out_string, **options) {|row| … } filter(in_io, out_io, **options) {|row| … }.
-
.foreach(path, mode = "r", **options, &block) ⇒ Object
:call-seq: foreach(path, mode=‘r’, **options) {|row| … ) foreach(io, mode=‘r’, **options {|row| … ) foreach(path, mode=‘r’, headers: …, **options) {|row| … ) foreach(io, mode=‘r’, headers: …, **options {|row| … ) foreach(path, mode=‘r’, **options) -> new_enumerator foreach(io, mode=‘r’, **options -> new_enumerator.
-
.generate(str = nil, **options) {|csv| ... } ⇒ Object
:call-seq: generate(csv_string, **options) {|csv| … } generate(**options) {|csv| … }.
-
.generate_line(row, **options) ⇒ Object
:call-seq: CSV.generate_line(ary) CSV.generate_line(ary, **options).
-
.instance(data = $stdout, **options) ⇒ Object
:call-seq: instance(string, **options) instance(io = $stdout, **options) instance(string, **options) {|csv| … } instance(io = $stdout, **options) {|csv| … }.
-
.open(filename, mode = "r", **options) ⇒ Object
:call-seq: open(file_path, mode = “rb”, **options ) -> new_csv open(io, mode = “rb”, **options ) -> new_csv open(file_path, mode = “rb”, **options ) { |csv| … } -> object open(io, mode = “rb”, **options ) { |csv| … } -> object.
-
.parse(str, **options, &block) ⇒ Object
:call-seq: parse(string) -> array_of_arrays parse(io) -> array_of_arrays parse(string, headers: …, **options) -> csv_table parse(io, headers: …, **options) -> csv_table parse(string, **options) {|row| … } parse(io, **options) {|row| … }.
-
.parse_line(line, **options) ⇒ Object
:call-seq: CSV.parse_line(string) -> new_array or nil CSV.parse_line(io) -> new_array or nil CSV.parse_line(string, **options) -> new_array or nil CSV.parse_line(io, **options) -> new_array or nil CSV.parse_line(string, headers: true, **options) -> csv_row or nil CSV.parse_line(io, headers: true, **options) -> csv_row or nil.
-
.read(path, **options) ⇒ Object
:call-seq: read(source, **options) -> array_of_arrays read(source, headers: true, **options) -> csv_table.
-
.readlines(path, **options) ⇒ Object
:call-seq: CSV.readlines(source, **options).
-
.table(path, **options) ⇒ Object
:call-seq: CSV.table(source, **options).
Instance Method Summary collapse
-
#<<(row) ⇒ Object
(also: #add_row, #puts)
:call-seq: csv.<< row.
- #binmode? ⇒ Boolean
-
#col_sep ⇒ Object
:call-seq: csv.col_sep -> string.
-
#convert(name = nil, &converter) ⇒ Object
:call-seq: convert(converter_name) -> array_of_procs convert {|field, field_info| … } -> array_of_procs.
-
#converters ⇒ Object
:call-seq: csv.converters -> array.
-
#each(&block) ⇒ Object
Yields each row of the data source in turn.
- #eof? ⇒ Boolean (also: #eof)
-
#field_size_limit ⇒ Object
:call-seq: csv.field_size_limit -> integer or nil.
- #flock(*args) ⇒ Object
-
#force_quotes? ⇒ Boolean
:call-seq: csv.force_quotes? -> true or false.
-
#header_convert(name = nil, &converter) ⇒ Object
The block need not return a String object: csv = CSV.open(path, headers: true) csv.header_convert {|header, field_info| header.to_sym } table = csv.read table.headers # => [:Name, :Value].
-
#header_converters ⇒ Object
:call-seq: csv.header_converters -> array.
-
#header_row? ⇒ Boolean
Returns
trueif the next row read will be a header row. -
#headers ⇒ Object
:call-seq: csv.headers -> object.
-
#initialize(data, 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, skip_lines: nil, liberal_parsing: false, internal_encoding: nil, external_encoding: nil, encoding: nil, nil_value: nil, empty_value: "", quote_empty: true, write_converters: nil, write_nil_value: nil, write_empty_value: "", strip: false) ⇒ CSV
constructor
:call-seq: CSV.new(string) CSV.new(io) CSV.new(string, **options) CSV.new(io, **options).
-
#inspect ⇒ Object
Returns a simplified description of the key CSV attributes in an ASCII compatible String.
- #ioctl(*args) ⇒ Object
-
#liberal_parsing? ⇒ Boolean
:call-seq: csv.liberal_parsing? -> true or false.
-
#line ⇒ Object
:call-seq: csv.line -> array.
-
#lineno ⇒ Object
:call-seq: csv.line_no -> integer.
- #path ⇒ Object
-
#quote_char ⇒ Object
:call-seq: csv.quote_char -> character.
-
#read ⇒ Object
(also: #readlines)
:call-seq: read.
-
#return_headers? ⇒ Boolean
:call-seq: csv.return_headers? -> true or false.
-
#rewind ⇒ Object
Rewinds the underlying IO object and resets CSV’s lineno() counter.
-
#row_sep ⇒ Object
:call-seq: csv.row_sep -> string.
-
#shift ⇒ Object
(also: #gets, #readline)
The primary read method for wrapped Strings and IOs, a single row is pulled from the data source, parsed and returned as an Array of fields (if header rows are not used) or a CSV::Row (when header rows are used).
-
#skip_blanks? ⇒ Boolean
:call-seq: csv.skip_blanks? -> true or false.
-
#skip_lines ⇒ Object
:call-seq: csv.skip_lines -> regexp or nil.
- #stat(*args) ⇒ Object
- #to_i ⇒ Object
- #to_io ⇒ Object
-
#unconverted_fields? ⇒ Boolean
:call-seq: csv.unconverted_fields? -> object.
-
#write_headers? ⇒ Boolean
:call-seq: csv.write_headers? -> true or false.
Constructor Details
#initialize(data, 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, skip_lines: nil, liberal_parsing: false, internal_encoding: nil, external_encoding: nil, encoding: nil, nil_value: nil, empty_value: "", quote_empty: true, write_converters: nil, write_nil_value: nil, write_empty_value: "", strip: false) ⇒ CSV
:call-seq:
CSV.new(string)
CSV.new(io)
CSV.new(string, **)
CSV.new(io, **)
Returns the new CSV object created using string or io and the specified options.
-
Argument
stringshould be a String object; it will be put into a new StringIO object positioned at the beginning.
:include: ../doc/arguments/io.rdoc
-
Argument
options: See:For performance reasons, the options cannot be overridden in a CSV object, so those specified here will endure.
In addition to the CSV instance methods, several IO methods are delegated. See Delegated Methods.
Create a CSV object from a String object:
csv = CSV.new('foo,0')
csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
Create a CSV object from a File object:
File.write('t.csv', 'foo,0')
csv = CSV.new(File.open('t.csv'))
csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
Raises an exception if the argument is nil:
# Raises ArgumentError (Cannot parse nil as CSV):
CSV.new(nil)
1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 |
# File 'lib/csv.rb', line 1702 def initialize(data, 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, skip_lines: nil, liberal_parsing: false, internal_encoding: nil, external_encoding: nil, encoding: nil, nil_value: nil, empty_value: "", quote_empty: true, write_converters: nil, write_nil_value: nil, write_empty_value: "", strip: false) raise ArgumentError.new("Cannot parse nil as CSV") if data.nil? if data.is_a?(String) @io = StringIO.new(data) @io.set_encoding(encoding || data.encoding) else @io = data end @encoding = determine_encoding(encoding, internal_encoding) @base_fields_converter_options = { nil_value: nil_value, empty_value: empty_value, } @write_fields_converter_options = { nil_value: write_nil_value, empty_value: write_empty_value, } @initial_converters = converters @initial_header_converters = header_converters @initial_write_converters = write_converters @parser_options = { column_separator: col_sep, row_separator: row_sep, quote_character: quote_char, field_size_limit: field_size_limit, unconverted_fields: unconverted_fields, headers: headers, return_headers: return_headers, skip_blanks: skip_blanks, skip_lines: skip_lines, liberal_parsing: liberal_parsing, encoding: @encoding, nil_value: nil_value, empty_value: empty_value, strip: strip, } @parser = nil @parser_enumerator = nil @eof_error = nil @writer_options = { encoding: @encoding, force_encoding: (not encoding.nil?), force_quotes: force_quotes, headers: headers, write_headers: write_headers, column_separator: col_sep, row_separator: row_sep, quote_character: quote_char, quote_empty: quote_empty, } @writer = nil writer if @writer_options[:write_headers] end |
Instance Attribute Details
#encoding ⇒ Object (readonly)
:call-seq:
csv.encoding -> endcoding
Returns the encoding used for parsing and generating; see Character Encodings (M17n or Multilingualization):
CSV.new('').encoding # => #<Encoding:UTF-8>
1952 1953 1954 |
# File 'lib/csv.rb', line 1952 def encoding @encoding end |
Class Method Details
.filter(input = nil, output = nil, **options) ⇒ Object
:call-seq:
filter(**options) {|row| ... }
filter(in_string, **options) {|row| ... }
filter(in_io, **options) {|row| ... }
filter(in_string, out_string, **options) {|row| ... }
filter(in_string, out_io, **options) {|row| ... }
filter(in_io, out_string, **options) {|row| ... }
filter(in_io, out_io, **options) {|row| ... }
Reads CSV input and writes CSV output.
For each input row:
-
Forms the data into:
-
A CSV::Row object, if headers are in use.
-
An Array of Arrays, otherwise.
-
-
Calls the block with that object.
-
Appends the block’s return value to the output.
Arguments:
-
CSV source:
-
Argument
in_string, if given, should be a String object; it will be put into a new StringIO object positioned at the beginning. -
Argument
in_io, if given, should be an IO object that is open for reading; on return, the IO object will be closed. -
If neither
in_stringnorin_iois given, the input stream defaults to ARGF.
-
-
CSV output:
-
Argument
out_string, if given, should be a String object; it will be put into a new StringIO object positioned at the beginning. -
Argument
out_io, if given, should be an IO object that is ppen for writing; on return, the IO object will be closed. -
If neither
out_stringnorout_iois given, the output stream defaults to$stdout.
-
-
Argument
optionsshould be keyword arguments.-
Each argument name that is prefixed with
in_orinput_is stripped of its prefix and is treated as an option for parsing the input. Optioninput_row_sepdefaults to$INPUT_RECORD_SEPARATOR. -
Each argument name that is prefixed with
out_oroutput_is stripped of its prefix and is treated as an option for generating the output. Optionoutput_row_sepdefaults to$INPUT_RECORD_SEPARATOR. -
Each argument not prefixed as above is treated as an option both for parsing the input and for generating the output.
-
Example:
in_string = "foo,0\nbar,1\nbaz,2\n"
out_string = ''
CSV.filter(in_string, out_string) do |row|
row[0] = row[0].upcase
row[1] *= 4
end
out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n"
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 |
# File 'lib/csv.rb', line 1041 def filter(input=nil, output=nil, **) # parse options for input, output, or both , = Hash.new, {row_sep: $INPUT_RECORD_SEPARATOR} .each do |key, value| case key.to_s when /\Ain(?:put)?_(.+)\Z/ [$1.to_sym] = value when /\Aout(?:put)?_(.+)\Z/ [$1.to_sym] = value else [key] = value [key] = value end end # build input and output wrappers input = new(input || ARGF, **) output = new(output || $stdout, **) # read, yield, write input.each do |row| yield row output << row end end |
.foreach(path, mode = "r", **options, &block) ⇒ Object
:call-seq:
foreach(path, mode='r', **options) {|row| ... )
foreach(io, mode='r', **options {|row| ... )
foreach(path, mode='r', headers: ..., **options) {|row| ... )
foreach(io, mode='r', headers: ..., **options {|row| ... )
foreach(path, mode='r', **options) -> new_enumerator
foreach(io, mode='r', **options -> new_enumerator
Calls the block with each row read from source path or io.
-
Argument
path, if given, must be the path to a file.
:include: ../doc/arguments/io.rdoc
-
Argument
mode, if given, must be a File mode See Open Mode. -
Arguments
**optionsmust be keyword options. See Options for Parsing. -
This method optionally accepts an additional
:encodingoption that you can use to specify the Encoding of the data read frompathorio. You must provide this unless your data is in the encoding given byEncoding::default_external. Parsing will use this to determine how to parse the data. You may provide a second Encoding to have the data transcoded as it is read. For example,encoding: 'UTF-32BE:UTF-8'would read
UTF-32BEdata from the file but transcode it toUTF-8before parsing.
Without Option headers
Without option headers, returns each row as an Array object.
These examples assume prior execution of:
string = "foo,0\nbar,1\nbaz,2\n"
path = 't.csv'
File.write(path, string)
Read rows from a file at path:
CSV.foreach(path) {|row| p row }
Output:
["foo", "0"]
["bar", "1"]
["baz", "2"]
Read rows from an IO object:
File.open(path) do |file|
CSV.foreach(file) {|row| p row }
end
Output:
["foo", "0"]
["bar", "1"]
["baz", "2"]
Returns a new Enumerator if no block given:
CSV.foreach(path) # => #<Enumerator: CSV:foreach("t.csv", "r")>
CSV.foreach(File.open(path)) # => #<Enumerator: CSV:foreach(#<File:t.csv>, "r")>
Issues a warning if an encoding is unsupported:
CSV.foreach(File.open(path), encoding: 'foo:bar') {|row| }
Output:
warning: Unsupported encoding foo ignored
warning: Unsupported encoding bar ignored
With Option headers
With option headers, returns each row as a CSV::Row object.
These examples assume prior execution of:
string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n"
path = 't.csv'
File.write(path, string)
Read rows from a file at path:
CSV.foreach(path, headers: true) {|row| p row }
Output:
#<CSV::Row "Name":"foo" "Count":"0">
#<CSV::Row "Name":"bar" "Count":"1">
#<CSV::Row "Name":"baz" "Count":"2">
Read rows from an IO object:
File.open(path) do |file|
CSV.foreach(file, headers: true) {|row| p row }
end
Output:
#<CSV::Row "Name":"foo" "Count":"0">
#<CSV::Row "Name":"bar" "Count":"1">
#<CSV::Row "Name":"baz" "Count":"2">
Raises an exception if path is a String, but not the path to a readable file:
# Raises Errno::ENOENT (No such file or directory @ rb_sysopen - nosuch.csv):
CSV.foreach('nosuch.csv') {|row| }
Raises an exception if io is an IO object, but not open for reading:
io = File.open(path, 'w') {|row| }
# Raises TypeError (no implicit conversion of nil into String):
CSV.foreach(io) {|row| }
Raises an exception if mode is invalid:
# Raises ArgumentError (invalid access mode nosuch):
CSV.foreach(path, 'nosuch') {|row| }
1173 1174 1175 1176 1177 1178 |
# File 'lib/csv.rb', line 1173 def foreach(path, mode="r", **, &block) return to_enum(__method__, path, mode, **) unless block_given? open(path, mode, **) do |csv| csv.each(&block) end end |
.generate(str = nil, **options) {|csv| ... } ⇒ Object
:call-seq:
generate(csv_string, **options) {|csv| ... }
generate(**options) {|csv| ... }
-
Argument
csv_string, if given, must be a String object; defaults to a new empty String. -
Arguments
options, if given, should be generating options. See Options for Generating.
Creates a new CSV object via CSV.new(csv_string, **options); calls the block with the CSV object, which the block may modify; returns the String generated from the CSV object.
Note that a passed String is modified by this method. Pass csv_string.dup if the String must be preserved.
This method has one additional option: :encoding, which sets the base Encoding for the output if no no str is specified. CSV needs this hint if you plan to output non-ASCII compatible data.
Add lines:
input_string = "foo,0\nbar,1\nbaz,2\n"
output_string = CSV.generate(input_string) do |csv|
csv << ['bat', 3]
csv << ['bam', 4]
end
output_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n"
input_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n"
output_string.equal?(input_string) # => true # Same string, modified
Add lines into new string, preserving old string:
input_string = "foo,0\nbar,1\nbaz,2\n"
output_string = CSV.generate(input_string.dup) do |csv|
csv << ['bat', 3]
csv << ['bam', 4]
end
output_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n"
input_string # => "foo,0\nbar,1\nbaz,2\n"
output_string.equal?(input_string) # => false # Different strings
Create lines from nothing:
output_string = CSV.generate do |csv|
csv << ['foo', 0]
csv << ['bar', 1]
csv << ['baz', 2]
end
output_string # => "foo,0\nbar,1\nbaz,2\n"
Raises an exception if csv_string is not a String object:
# Raises TypeError (no implicit conversion of Integer into String)
CSV.generate(0)
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 |
# File 'lib/csv.rb', line 1239 def generate(str=nil, **) encoding = [:encoding] # add a default empty String, if none was given if str str = StringIO.new(str) str.seek(0, IO::SEEK_END) str.set_encoding(encoding) if encoding else str = +"" str.force_encoding(encoding) if encoding end csv = new(str, **) # wrap yield csv # yield for appending csv.string # return final String end |
.generate_line(row, **options) ⇒ Object
:call-seq:
CSV.generate_line(ary)
CSV.generate_line(ary, **)
Returns the String created by generating CSV from ary using the specified options.
Argument ary must be an Array.
Special options:
-
Option
:row_sepdefaults to$INPUT_RECORD_SEPARATOR($/).:$INPUT_RECORD_SEPARATOR # => "\n" -
This method accepts an additional option,
:encoding, which sets the base Encoding for the output. This method will try to guess your Encoding from the first non-nilfield inrow, if possible, but you may need to use this parameter as a backup plan.
For other options, see Options for Generating.
Returns the String generated from an Array:
CSV.generate_line(['foo', '0']) # => "foo,0\n"
Raises an exception if ary is not an Array:
# Raises NoMethodError (undefined method `find' for :foo:Symbol)
CSV.generate_line(:foo)
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 |
# File 'lib/csv.rb', line 1287 def generate_line(row, **) = {row_sep: $INPUT_RECORD_SEPARATOR}.merge() str = +"" if [:encoding] str.force_encoding([:encoding]) else fallback_encoding = nil output_encoding = nil row.each do |field| next unless field.is_a?(String) fallback_encoding ||= field.encoding next if field.ascii_only? output_encoding = field.encoding break end output_encoding ||= fallback_encoding if output_encoding str.force_encoding(output_encoding) end end (new(str, **) << row).string end |
.instance(data = $stdout, **options) ⇒ Object
:call-seq:
instance(string, **options)
instance(io = $stdout, **options)
instance(string, **options) {|csv| ... }
instance(io = $stdout, **options) {|csv| ... }
Creates or retrieves cached CSV objects. For arguments and options, see CSV.new.
With no block given, returns a CSV object.
The first call to instance creates and caches a CSV object:
s0 = 's0'
csv0 = CSV.instance(s0)
csv0.class # => CSV
Subsequent calls to instance with that same string or io retrieve that same cached object:
csv1 = CSV.instance(s0)
csv1.class # => CSV
csv1.equal?(csv0) # => true # Same CSV object
A subsequent call to instance with a different string or io creates and caches a different CSV object.
s1 = 's1'
csv2 = CSV.instance(s1)
csv2.equal?(csv0) # => false # Different CSV object
All the cached objects remains available:
csv3 = CSV.instance(s0)
csv3.equal?(csv0) # true # Same CSV object
csv4 = CSV.instance(s1)
csv4.equal?(csv2) # true # Same CSV object
When a block is given, calls the block with the created or retrieved CSV object; returns the block’s return value:
CSV.instance(s0) {|csv| :foo } # => :foo
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 |
# File 'lib/csv.rb', line 970 def instance(data = $stdout, **) # create a _signature_ for this method call, data object and options sig = [data.object_id] + .values_at(*DEFAULT_OPTIONS.keys.sort_by { |sym| sym.to_s }) # fetch or create the instance for this signature @@instances ||= Hash.new instance = (@@instances[sig] ||= new(data, **)) if block_given? yield instance # run block, if given, returning result else instance # or return the instance end end |
.open(filename, mode = "r", **options) ⇒ Object
:call-seq:
open(file_path, mode = "rb", **options ) -> new_csv
open(io, mode = "rb", **options ) -> new_csv
open(file_path, mode = "rb", **options ) { |csv| ... } -> object
open(io, mode = "rb", **options ) { |csv| ... } -> object
possible options elements:
hash form:
:invalid => nil # raise error on invalid byte sequence (default)
:invalid => :replace # replace invalid byte sequence
:undef => :replace # replace undefined conversion
:replace => string # replacement string ("?" or "\uFFFD" if not specified)
-
Argument
path, if given, must be the path to a file.
:include: ../doc/arguments/io.rdoc
-
Argument
mode, if given, must be a File mode See Open Mode. -
Arguments
**optionsmust be keyword options. See Options for Generating. -
This method optionally accepts an additional
:encodingoption that you can use to specify the Encoding of the data read frompathorio. You must provide this unless your data is in the encoding given byEncoding::default_external. Parsing will use this to determine how to parse the data. You may provide a second Encoding to have the data transcoded as it is read. For example,encoding: 'UTF-32BE:UTF-8'would read
UTF-32BEdata from the file but transcode it toUTF-8before parsing.
These examples assume prior execution of:
string = "foo,0\nbar,1\nbaz,2\n"
path = 't.csv'
File.write(path, string)
With no block given, returns a new CSV object.
Create a CSV object using a file path:
csv = CSV.open(path)
csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
Create a CSV object using an open File:
csv = CSV.open(File.open(path))
csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
With a block given, calls the block with the created CSV object; returns the block’s return value:
Using a file path:
csv = CSV.open(path) {|csv| p csv}
csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
Output:
#<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
Using an open File:
csv = CSV.open(File.open(path)) {|csv| p csv}
csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
Output:
#<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
Raises an exception if the argument is not a String object or IO object:
# Raises TypeError (no implicit conversion of Symbol into String)
CSV.open(:foo)
1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 |
# File 'lib/csv.rb', line 1382 def open(filename, mode="r", **) # wrap a File opened with the remaining +args+ with no newline # decorator file_opts = {universal_newline: false}.merge() .delete(:invalid) .delete(:undef) .delete(:replace) begin f = File.open(filename, mode, **file_opts) rescue ArgumentError => e raise unless /needs binmode/.match?(e.) and mode == "r" mode = "rb" file_opts = {encoding: Encoding.default_external}.merge(file_opts) retry end begin csv = new(f, **) rescue Exception f.close raise end # handle blocks like Ruby's open(), not like the CSV library if block_given? begin yield csv ensure csv.close end else csv end end |
.parse(str, **options, &block) ⇒ Object
:call-seq:
parse(string) -> array_of_arrays
parse(io) -> array_of_arrays
parse(string, headers: ..., **options) -> csv_table
parse(io, headers: ..., **options) -> csv_table
parse(string, **options) {|row| ... }
parse(io, **options) {|row| ... }
Parses string or io using the specified options.
-
Argument
stringshould be a String object; it will be put into a new StringIO object positioned at the beginning.
:include: ../doc/arguments/io.rdoc
-
Argument
options: see Options for Parsing
Without Option headers
Without option headers case.
These examples assume prior execution of:
string = "foo,0\nbar,1\nbaz,2\n"
path = 't.csv'
File.write(path, string)
With no block given, returns an Array of Arrays formed from the source.
Parse a String:
a_of_a = CSV.parse(string)
a_of_a # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
Parse an open File:
a_of_a = File.open(path) do |file|
CSV.parse(file)
end
a_of_a # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
With a block given, calls the block with each parsed row:
Parse a String:
CSV.parse(string) {|row| p row }
Output:
["foo", "0"]
["bar", "1"]
["baz", "2"]
Parse an open File:
File.open(path) do |file|
CSV.parse(file) {|row| p row }
end
Output:
["foo", "0"]
["bar", "1"]
["baz", "2"]
With Option headers
With option headers case.
These examples assume prior execution of:
string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n"
path = 't.csv'
File.write(path, string)
With no block given, returns a CSV::Table object formed from the source.
Parse a String:
csv_table = CSV.parse(string, headers: ['Name', 'Count'])
csv_table # => #<CSV::Table mode:col_or_row row_count:5>
Parse an open File:
csv_table = File.open(path) do |file|
CSV.parse(file, headers: ['Name', 'Count'])
end
csv_table # => #<CSV::Table mode:col_or_row row_count:4>
With a block given, calls the block with each parsed row, which has been formed into a CSV::Row object:
Parse a String:
CSV.parse(string, headers: ['Name', 'Count']) {|row| p row }
Output:
# <CSV::Row "Name":"foo" "Count":"0">
# <CSV::Row "Name":"bar" "Count":"1">
# <CSV::Row "Name":"baz" "Count":"2">
Parse an open File:
File.open(path) do |file|
CSV.parse(file, headers: ['Name', 'Count']) {|row| p row }
end
Output:
# <CSV::Row "Name":"foo" "Count":"0">
# <CSV::Row "Name":"bar" "Count":"1">
# <CSV::Row "Name":"baz" "Count":"2">
Raises an exception if the argument is not a String object or IO object:
# Raises NoMethodError (undefined method `close' for :foo:Symbol)
CSV.parse(:foo)
1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 |
# File 'lib/csv.rb', line 1529 def parse(str, **, &block) csv = new(str, **) return csv.each(&block) if block_given? # slurp contents, if no block is given begin csv.read ensure csv.close end end |
.parse_line(line, **options) ⇒ Object
:call-seq:
CSV.parse_line(string) -> new_array or nil
CSV.parse_line(io) -> new_array or nil
CSV.parse_line(string, **options) -> new_array or nil
CSV.parse_line(io, **options) -> new_array or nil
CSV.parse_line(string, headers: true, **options) -> csv_row or nil
CSV.parse_line(io, headers: true, **options) -> csv_row or nil
Returns the data created by parsing the first line of string or io using the specified options.
-
Argument
stringshould be a String object; it will be put into a new StringIO object positioned at the beginning.
:include: ../doc/arguments/io.rdoc
-
Argument
options: see Options for Parsing
Without Option headers
Without option headers, returns the first row as a new Array.
These examples assume prior execution of:
string = "foo,0\nbar,1\nbaz,2\n"
path = 't.csv'
File.write(path, string)
Parse the first line from a String object:
CSV.parse_line(string) # => ["foo", "0"]
Parse the first line from a File object:
File.open(path) do |file|
CSV.parse_line(file) # => ["foo", "0"]
end # => ["foo", "0"]
Returns nil if the argument is an empty String:
CSV.parse_line('') # => nil
With Option headers
With option headers, returns the first row as a CSV::Row object.
These examples assume prior execution of:
string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n"
path = 't.csv'
File.write(path, string)
Parse the first line from a String object:
CSV.parse_line(string, headers: true) # => #<CSV::Row "Name":"foo" "Count":"0">
Parse the first line from a File object:
File.open(path) do |file|
CSV.parse_line(file, headers: true)
end # => #<CSV::Row "Name":"foo" "Count":"0">
Raises an exception if the argument is nil:
# Raises ArgumentError (Cannot parse nil as CSV):
CSV.parse_line(nil)
1602 1603 1604 |
# File 'lib/csv.rb', line 1602 def parse_line(line, **) new(line, **).each.first end |
.read(path, **options) ⇒ Object
:call-seq:
read(source, **options) -> array_of_arrays
read(source, headers: true, **options) -> csv_table
Opens the given source with the given options (see CSV.open), reads the source (see CSV#read), and returns the result, which will be either an Array of Arrays or a CSV::Table.
Without headers:
string = "foo,0\nbar,1\nbaz,2\n"
path = 't.csv'
File.write(path, string)
CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
With headers:
string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
path = 't.csv'
File.write(path, string)
CSV.read(path, headers: true) # => #<CSV::Table mode:col_or_row row_count:4>
1626 1627 1628 |
# File 'lib/csv.rb', line 1626 def read(path, **) open(path, **) { |csv| csv.read } end |
.readlines(path, **options) ⇒ Object
1634 1635 1636 |
# File 'lib/csv.rb', line 1634 def readlines(path, **) read(path, **) end |
.table(path, **options) ⇒ Object
:call-seq:
CSV.table(source, **)
Calls CSV.read with source, options, and certain default options:
-
headers:true -
converbers::numeric -
header_converters::symbol
Returns a CSV::Table object.
Example:
string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
path = 't.csv'
File.write(path, string)
CSV.table(path) # => #<CSV::Table mode:col_or_row row_count:4>
1653 1654 1655 1656 1657 1658 1659 1660 1661 |
# File 'lib/csv.rb', line 1653 def table(path, **) = { headers: true, converters: :numeric, header_converters: :symbol, } = .merge() read(path, **) end |
Instance Method Details
#<<(row) ⇒ Object Also known as: add_row, puts
:call-seq:
csv.<< row
Appends a row to self.
-
Argument
rowmust be an Array object or a CSV::Row object. -
The output stream must be open for writing.
Append Arrays:
CSV.generate do |csv|
csv << ['foo', 0]
csv << ['bar', 1]
csv << ['baz', 2]
end # => "foo,0\nbar,1\nbaz,2\n"
Append CSV::Rows:
headers = []
CSV.generate do |csv|
csv << CSV::Row.new(headers, ['foo', 0])
csv << CSV::Row.new(headers, ['bar', 1])
csv << CSV::Row.new(headers, ['baz', 2])
end # => "foo,0\nbar,1\nbaz,2\n"
Headers in CSV::Row objects are not appended:
headers = ['Name', 'Count']
CSV.generate do |csv|
csv << CSV::Row.new(headers, ['foo', 0])
csv << CSV::Row.new(headers, ['bar', 1])
csv << CSV::Row.new(headers, ['baz', 2])
end # => "foo,0\nbar,1\nbaz,2\n"
Raises an exception if row is not an Array or CSV::Row:
CSV.generate do |csv|
# Raises NoMethodError (undefined method `collect' for :foo:Symbol)
csv << :foo
end
Raises an exception if the output stream is not open for writing:
path = 't.csv'
File.write(path, '')
File.open(path) do |file|
CSV.open(file) do |csv|
# Raises IOError (not opened for writing)
csv << ['foo', 0]
end
end
2132 2133 2134 2135 |
# File 'lib/csv.rb', line 2132 def <<(row) writer << row self end |
#binmode? ⇒ Boolean
2021 2022 2023 2024 2025 2026 2027 |
# File 'lib/csv.rb', line 2021 def binmode? if @io.respond_to?(:binmode?) @io.binmode? else false end end |
#col_sep ⇒ Object
:call-seq:
csv.col_sep -> string
Returns the encoded column separator; used for parsing and writing; see Option col_sep:
CSV.new('').col_sep # => ","
1791 1792 1793 |
# File 'lib/csv.rb', line 1791 def col_sep parser.column_separator end |
#convert(name = nil, &converter) ⇒ Object
:call-seq:
convert(converter_name) -> array_of_procs
convert {|field, field_info| ... } -> array_of_procs
-
With no block, installs a field converter (a Proc).
-
With a block, defines and installs a custom field converter.
-
Returns the Array of installed field converters.
-
Argument
converter_name, if given, should be the name of an existing field converter.
See Field Converters.
With no block, installs a field converter:
csv = CSV.new('')
csv.convert(:integer)
csv.convert(:float)
csv.convert(:date)
csv.converters # => [:integer, :float, :date]
The block, if given, is called for each field:
-
Argument
fieldis the field value. -
Argument
field_infois a CSV::FieldInfo object containing details about the field.
The examples here assume the prior execution of:
string = "foo,0\nbar,1\nbaz,2\n"
path = 't.csv'
File.write(path, string)
Example giving a block:
csv = CSV.open(path)
csv.convert {|field, field_info| p [field, field_info]; field.upcase }
csv.read # => [["FOO", "0"], ["BAR", "1"], ["BAZ", "2"]]
Output:
["foo", #<struct CSV::FieldInfo index=0, line=1, header=nil>]
["0", #<struct CSV::FieldInfo index=1, line=1, header=nil>]
["bar", #<struct CSV::FieldInfo index=0, line=2, header=nil>]
["1", #<struct CSV::FieldInfo index=1, line=2, header=nil>]
["baz", #<struct CSV::FieldInfo index=0, line=3, header=nil>]
["2", #<struct CSV::FieldInfo index=1, line=3, header=nil>]
The block need not return a String object:
csv = CSV.open(path)
csv.convert {|field, field_info| field.to_sym }
csv.read # => [[:foo, :"0"], [:bar, :"1"], [:baz, :"2"]]
If converter_name is given, the block is not called:
csv = CSV.open(path)
csv.convert(:integer) {|field, field_info| fail 'Cannot happen' }
csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]]
Raises a parse-time exception if converter_name is not the name of a built-in field converter:
csv = CSV.open(path)
csv.convert(:nosuch) => [nil]
# Raises NoMethodError (undefined method `arity' for nil:NilClass)
csv.read
2203 2204 2205 |
# File 'lib/csv.rb', line 2203 def convert(name = nil, &converter) parser_fields_converter.add_converter(name, &converter) end |
#converters ⇒ Object
:call-seq:
csv.converters -> array
Returns an Array containing field converters; see Field Converters:
csv = CSV.new('')
csv.converters # => []
csv.convert(:integer)
csv.converters # => [:integer]
csv.convert(proc {|x| x.to_s })
csv.converters
1846 1847 1848 1849 1850 1851 |
# File 'lib/csv.rb', line 1846 def converters parser_fields_converter.map do |converter| name = Converters.rassoc(converter) name ? name.first : converter end end |
#each(&block) ⇒ Object
Yields each row of the data source in turn.
Support for Enumerable.
The data source must be open for reading.
2282 2283 2284 |
# File 'lib/csv.rb', line 2282 def each(&block) parser_enumerator.each(&block) end |
#eof? ⇒ Boolean Also known as: eof
2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 |
# File 'lib/csv.rb', line 2057 def eof? return false if @eof_error begin parser_enumerator.peek false rescue MalformedCSVError => error @eof_error = error false rescue StopIteration true end end |
#field_size_limit ⇒ Object
:call-seq:
csv.field_size_limit -> integer or nil
Returns the limit for field size; used for parsing; see Option field_size_limit:
CSV.new('').field_size_limit # => nil
1821 1822 1823 |
# File 'lib/csv.rb', line 1821 def field_size_limit parser.field_size_limit end |
#flock(*args) ⇒ Object
2029 2030 2031 2032 |
# File 'lib/csv.rb', line 2029 def flock(*args) raise NotImplementedError unless @io.respond_to?(:flock) @io.flock(*args) end |
#force_quotes? ⇒ Boolean
:call-seq:
csv.force_quotes? -> true or false
Returns the value that determines whether all output fields are to be quoted; used for generating; see Option force_quotes:
CSV.new('').force_quotes? # => false
1932 1933 1934 |
# File 'lib/csv.rb', line 1932 def force_quotes? @writer_options[:force_quotes] end |
#header_convert(name = nil, &converter) ⇒ Object
The block need not return a String object:
csv = CSV.open(path, headers: true)
csv.header_convert {|header, field_info| header.to_sym }
table = csv.read
table.headers # => [:Name, :Value]
If converter_name is given, the block is not called:
csv = CSV.open(path, headers: true)
csv.header_convert(:downcase) {|header, field_info| fail 'Cannot happen' }
table = csv.read
table.headers # => ["name", "value"]
Raises a parse-time exception if converter_name is not the name of a built-in field converter:
csv = CSV.open(path, headers: true)
csv.header_convert(:nosuch)
# Raises NoMethodError (undefined method `arity' for nil:NilClass)
csv.read
2269 2270 2271 |
# File 'lib/csv.rb', line 2269 def header_convert(name = nil, &converter) header_fields_converter.add_converter(name, &converter) end |
#header_converters ⇒ Object
:call-seq:
csv.header_converters -> array
Returns an Array containing header converters; used for parsing; see Header Converters:
CSV.new('').header_converters # => []
1908 1909 1910 1911 1912 1913 |
# File 'lib/csv.rb', line 1908 def header_converters header_fields_converter.map do |converter| name = HeaderConverters.rassoc(converter) name ? name.first : converter end end |
#header_row? ⇒ Boolean
Returns true if the next row read will be a header row.
2319 2320 2321 |
# File 'lib/csv.rb', line 2319 def header_row? parser.header_row? end |
#headers ⇒ Object
:call-seq:
csv.headers -> object
Returns the value that determines whether headers are used; used for parsing; see Option headers:
CSV.new('').headers # => nil
1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 |
# File 'lib/csv.rb', line 1870 def headers if @writer @writer.headers else parsed_headers = parser.headers return parsed_headers if parsed_headers raw_headers = @parser_options[:headers] raw_headers = nil if raw_headers == false raw_headers end end |
#inspect ⇒ Object
Returns a simplified description of the key CSV attributes in an ASCII compatible String.
2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 |
# File 'lib/csv.rb', line 2348 def inspect str = ["#<", self.class.to_s, " io_type:"] # show type of wrapped IO if @io == $stdout then str << "$stdout" elsif @io == $stdin then str << "$stdin" elsif @io == $stderr then str << "$stderr" else str << @io.class.to_s end # show IO.path(), if available if @io.respond_to?(:path) and (p = @io.path) str << " io_path:" << p.inspect end # show encoding str << " encoding:" << @encoding.name # show other attributes ["lineno", "col_sep", "row_sep", "quote_char"].each do |attr_name| if a = __send__(attr_name) str << " " << attr_name << ":" << a.inspect end end ["skip_blanks", "liberal_parsing"].each do |attr_name| if a = __send__("#{attr_name}?") str << " " << attr_name << ":" << a.inspect end end _headers = headers str << " headers:" << _headers.inspect if _headers str << ">" begin str.join('') rescue # any encoding error str.map do |s| e = Encoding::Converter.asciicompat_encoding(s.encoding) e ? s.encode(e) : s.force_encoding("ASCII-8BIT") end.join('') end end |
#ioctl(*args) ⇒ Object
2034 2035 2036 2037 |
# File 'lib/csv.rb', line 2034 def ioctl(*args) raise NotImplementedError unless @io.respond_to?(:ioctl) @io.ioctl(*args) end |
#liberal_parsing? ⇒ Boolean
:call-seq:
csv.liberal_parsing? -> true or false
Returns the value that determines whether illegal input is to be handled; used for parsing; see Option liberal_parsing:
CSV.new('').liberal_parsing? # => false
1942 1943 1944 |
# File 'lib/csv.rb', line 1942 def liberal_parsing? parser.liberal_parsing? end |
#line ⇒ Object
2007 2008 2009 |
# File 'lib/csv.rb', line 2007 def line parser.line end |
#lineno ⇒ Object
:call-seq:
csv.line_no -> integer
Returns the count of the rows parsed or generated.
Parsing:
string = "foo,0\nbar,1\nbaz,2\n"
path = 't.csv'
File.write(path, string)
CSV.open(path) do |csv|
csv.each do |row|
p [csv.lineno, row]
end
end
Output:
[1, ["foo", "0"]]
[2, ["bar", "1"]]
[3, ["baz", "2"]]
Generating:
CSV.generate do |csv|
p csv.lineno; csv << ['foo', 0]
p csv.lineno; csv << ['bar', 1]
p csv.lineno; csv << ['baz', 2]
end
Output:
0
1
2
1983 1984 1985 1986 1987 1988 1989 |
# File 'lib/csv.rb', line 1983 def lineno if @writer @writer.lineno else parser.lineno end end |
#path ⇒ Object
2039 2040 2041 |
# File 'lib/csv.rb', line 2039 def path @io.path if @io.respond_to?(:path) end |
#quote_char ⇒ Object
:call-seq:
csv.quote_char -> character
Returns the encoded quote character; used for parsing and writing; see Option quote_char:
CSV.new('').quote_char # => "\""
1811 1812 1813 |
# File 'lib/csv.rb', line 1811 def quote_char parser.quote_character end |
#read ⇒ Object Also known as: readlines
:call-seq:
read
Forms the remaining rows from self into:
-
A CSV::Table object, if headers are in use.
-
An Array of Arrays, otherwise.
The data source must be open for reading.
Without headers:
string = "foo,0\nbar,1\nbaz,2\n"
path = 't.csv'
File.write(path, string)
csv = CSV.open(path)
csv.read # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
With headers:
string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n"
path = 't.csv'
File.write(path, string)
csv = CSV.open(path, headers: true)
csv.read # => #<CSV::Table mode:col_or_row row_count:4>
2308 2309 2310 2311 2312 2313 2314 2315 |
# File 'lib/csv.rb', line 2308 def read rows = to_a if parser.use_headers? Table.new(rows, headers: parser.headers) else rows end end |
#return_headers? ⇒ Boolean
:call-seq:
csv.return_headers? -> true or false
Returns the value that determines whether headers are to be returned; used for parsing; see Option return_headers:
CSV.new('').return_headers? # => false
1888 1889 1890 |
# File 'lib/csv.rb', line 1888 def return_headers? parser.return_headers? end |
#rewind ⇒ Object
Rewinds the underlying IO object and resets CSV’s lineno() counter.
2072 2073 2074 2075 2076 2077 2078 |
# File 'lib/csv.rb', line 2072 def rewind @parser = nil @parser_enumerator = nil @eof_error = nil @writer.rewind if @writer @io.rewind end |
#row_sep ⇒ Object
:call-seq:
csv.row_sep -> string
Returns the encoded row separator; used for parsing and writing; see Option row_sep:
CSV.new('').row_sep # => "\n"
1801 1802 1803 |
# File 'lib/csv.rb', line 1801 def row_sep parser.row_separator end |
#shift ⇒ Object Also known as: gets, readline
The primary read method for wrapped Strings and IOs, a single row is pulled from the data source, parsed and returned as an Array of fields (if header rows are not used) or a CSV::Row (when header rows are used).
The data source must be open for reading.
2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 |
# File 'lib/csv.rb', line 2330 def shift if @eof_error eof_error, @eof_error = @eof_error, nil raise eof_error end begin parser_enumerator.next rescue StopIteration nil end end |
#skip_blanks? ⇒ Boolean
:call-seq:
csv.skip_blanks? -> true or false
Returns the value that determines whether blank lines are to be ignored; used for parsing; see Option skip_blanks:
CSV.new('').skip_blanks? # => false
1921 1922 1923 |
# File 'lib/csv.rb', line 1921 def skip_blanks? parser.skip_blanks? end |
#skip_lines ⇒ Object
:call-seq:
csv.skip_lines -> regexp or nil
Returns the Regexp used to identify comment lines; used for parsing; see Option skip_lines:
CSV.new('').skip_lines # => nil
1831 1832 1833 |
# File 'lib/csv.rb', line 1831 def skip_lines parser.skip_lines end |
#stat(*args) ⇒ Object
2043 2044 2045 2046 |
# File 'lib/csv.rb', line 2043 def stat(*args) raise NotImplementedError unless @io.respond_to?(:stat) @io.stat(*args) end |
#to_i ⇒ Object
2048 2049 2050 2051 |
# File 'lib/csv.rb', line 2048 def to_i raise NotImplementedError unless @io.respond_to?(:to_i) @io.to_i end |
#to_io ⇒ Object
2053 2054 2055 |
# File 'lib/csv.rb', line 2053 def to_io @io.respond_to?(:to_io) ? @io.to_io : @io end |
#unconverted_fields? ⇒ Boolean
:call-seq:
csv.unconverted_fields? -> object
Returns the value that determines whether unconverted fields are to be available; used for parsing; see Option unconverted_fields:
CSV.new('').unconverted_fields? # => nil
1860 1861 1862 |
# File 'lib/csv.rb', line 1860 def unconverted_fields? parser.unconverted_fields? end |
#write_headers? ⇒ Boolean
:call-seq:
csv.write_headers? -> true or false
Returns the value that determines whether headers are to be written; used for generating; see Option write_headers:
CSV.new('').write_headers? # => nil
1898 1899 1900 |
# File 'lib/csv.rb', line 1898 def write_headers? @writer_options[:write_headers] end |