Linux server1.dn-server.com 4.18.0-553.89.1.lve.el8.x86_64 #1 SMP Wed Dec 10 13:58:50 UTC 2025 x86_64
LiteSpeed
Server IP : 195.201.204.189 & Your IP : 216.73.217.103
Domains :
Cant Read [ /etc/named.conf ]
User : beriska1
Terminal
Auto Root
Create File
Create Folder
Localroot Suggester
Backdoor Destroyer
Readme
/
opt /
alt /
ruby33 /
share /
ri /
system /
CSV /
Delete
Unzip
Name
Size
Permission
Date
Action
FieldsConverter
[ DIR ]
drwxr-xr-x
2026-05-05 23:08
InputRecordSeparator
[ DIR ]
drwxr-xr-x
2026-05-05 23:08
InvalidEncodingError
[ DIR ]
drwxr-xr-x
2026-05-05 23:08
MalformedCSVError
[ DIR ]
drwxr-xr-x
2026-05-05 23:08
Parser
[ DIR ]
drwxr-xr-x
2026-05-05 23:08
Row
[ DIR ]
drwxr-xr-x
2026-05-05 23:08
Table
[ DIR ]
drwxr-xr-x
2026-05-05 23:08
Writer
[ DIR ]
drwxr-xr-x
2026-05-05 23:08
%3c%3c-i.ri
1.98
KB
-rw-r--r--
2026-04-07 17:22
add_row-i.ri
236
B
-rw-r--r--
2026-04-07 17:22
binmode%3f-i.ri
222
B
-rw-r--r--
2026-04-07 17:22
build_fields_converter-i.ri
277
B
-rw-r--r--
2026-04-07 17:22
build_header_fields_converter-i.ri
264
B
-rw-r--r--
2026-04-07 17:22
build_parser_fields_converter-i.ri
264
B
-rw-r--r--
2026-04-07 17:22
build_writer_fields_converter-i.ri
264
B
-rw-r--r--
2026-04-07 17:22
cdesc-CSV.ri
67.95
KB
-rw-r--r--
2026-04-07 17:22
col_sep-i.ri
492
B
-rw-r--r--
2026-04-07 17:22
convert-i.ri
2.96
KB
-rw-r--r--
2026-04-07 17:22
convert_fields-i.ri
631
B
-rw-r--r--
2026-04-07 17:22
converters-i.ri
765
B
-rw-r--r--
2026-04-07 17:22
determine_encoding-i.ri
269
B
-rw-r--r--
2026-04-07 17:22
each-i.ri
1.34
KB
-rw-r--r--
2026-04-07 17:22
encoding-i.ri
596
B
-rw-r--r--
2026-04-07 17:22
eof%3f-i.ri
241
B
-rw-r--r--
2026-04-07 17:22
eof-i.ri
227
B
-rw-r--r--
2026-04-07 17:22
field_size_limit-i.ri
607
B
-rw-r--r--
2026-04-07 17:22
filter-c.ri
6.09
KB
-rw-r--r--
2026-04-07 17:22
flock-i.ri
221
B
-rw-r--r--
2026-04-07 17:22
force_quotes%3f-i.ri
573
B
-rw-r--r--
2026-04-07 17:22
foreach-c.ri
3.23
KB
-rw-r--r--
2026-04-07 17:22
generate-c.ri
2.63
KB
-rw-r--r--
2026-04-07 17:22
generate_line-c.ri
1.6
KB
-rw-r--r--
2026-04-07 17:22
generate_lines-c.ri
1.66
KB
-rw-r--r--
2026-04-07 17:22
gets-i.ri
230
B
-rw-r--r--
2026-04-07 17:22
header_convert-i.ri
1.15
KB
-rw-r--r--
2026-04-07 17:22
header_converters-i.ri
675
B
-rw-r--r--
2026-04-07 17:22
header_fields_converter-i.ri
252
B
-rw-r--r--
2026-04-07 17:22
header_row%3f-i.ri
1.1
KB
-rw-r--r--
2026-04-07 17:22
headers-i.ri
502
B
-rw-r--r--
2026-04-07 17:22
inspect-i.ri
626
B
-rw-r--r--
2026-04-07 17:22
instance-c.ri
1.79
KB
-rw-r--r--
2026-04-07 17:22
ioctl-i.ri
221
B
-rw-r--r--
2026-04-07 17:22
liberal_parsing%3f-i.ri
577
B
-rw-r--r--
2026-04-07 17:22
line-i.ri
662
B
-rw-r--r--
2026-04-07 17:22
lineno-i.ri
999
B
-rw-r--r--
2026-04-07 17:22
max_field_size-i.ri
554
B
-rw-r--r--
2026-04-07 17:22
new-c.ri
2.7
KB
-rw-r--r--
2026-04-07 17:22
normalize_converters-i.ri
256
B
-rw-r--r--
2026-04-07 17:22
open-c.ri
3.99
KB
-rw-r--r--
2026-04-07 17:22
parse-c.ri
4.2
KB
-rw-r--r--
2026-04-07 17:22
parse_line-c.ri
3
KB
-rw-r--r--
2026-04-07 17:22
parser-i.ri
218
B
-rw-r--r--
2026-04-07 17:22
parser_enumerator-i.ri
240
B
-rw-r--r--
2026-04-07 17:22
parser_fields_converter-i.ri
252
B
-rw-r--r--
2026-04-07 17:22
parser_options-i.ri
234
B
-rw-r--r--
2026-04-07 17:22
path-i.ri
214
B
-rw-r--r--
2026-04-07 17:22
puts-i.ri
230
B
-rw-r--r--
2026-04-07 17:22
quote_char-i.ri
513
B
-rw-r--r--
2026-04-07 17:22
raw_encoding-i.ri
315
B
-rw-r--r--
2026-04-07 17:22
read-c.ri
1.03
KB
-rw-r--r--
2026-04-07 17:22
read-i.ri
1.4
KB
-rw-r--r--
2026-04-07 17:22
readline-i.ri
238
B
-rw-r--r--
2026-04-07 17:22
readlines-c.ri
336
B
-rw-r--r--
2026-04-07 17:22
readlines-i.ri
239
B
-rw-r--r--
2026-04-07 17:22
return_headers%3f-i.ri
567
B
-rw-r--r--
2026-04-07 17:22
rewind-i.ri
323
B
-rw-r--r--
2026-04-07 17:22
row_sep-i.ri
490
B
-rw-r--r--
2026-04-07 17:22
shift-i.ri
1.52
KB
-rw-r--r--
2026-04-07 17:22
skip_blanks%3f-i.ri
552
B
-rw-r--r--
2026-04-07 17:22
skip_lines-i.ri
519
B
-rw-r--r--
2026-04-07 17:22
stat-i.ri
219
B
-rw-r--r--
2026-04-07 17:22
table-c.ri
908
B
-rw-r--r--
2026-04-07 17:22
to_i-i.ri
214
B
-rw-r--r--
2026-04-07 17:22
to_io-i.ri
216
B
-rw-r--r--
2026-04-07 17:22
unconverted_fields%3f-i.ri
601
B
-rw-r--r--
2026-04-07 17:22
write_headers%3f-i.ri
561
B
-rw-r--r--
2026-04-07 17:22
writer-i.ri
218
B
-rw-r--r--
2026-04-07 17:22
writer_fields_converter-i.ri
252
B
-rw-r--r--
2026-04-07 17:22
writer_options-i.ri
234
B
-rw-r--r--
2026-04-07 17:22
Save
Rename
U:RDoc::NormalClass[iI"CSV:ET@I"Object;To:RDoc::Markup::Document:@parts[ o;;[vS:RDoc::Markup::Heading: leveli: textI" \CSV;To:RDoc::Markup::BlankLine S; ; i;I"\CSV Data;T@o:RDoc::Markup::Paragraph;[I"L\CSV (comma-separated values) data is a text representation of a table:;To:RDoc::Markup::List: @type:BULLET:@items[o:RDoc::Markup::ListItem:@label0;[o; ;[I".A _row_ _separator_ delimits table rows. ;TI"CA common row separator is the newline character <tt>"\n"</tt>.;To;;0;[o; ;[I"6A _column_ _separator_ delimits fields in a row. ;TI"CA common column separator is the comma character <tt>","</tt>.;T@o; ;[I"9This \CSV \String, with row separator <tt>"\n"</tt> ;TI"(and column separator <tt>","</tt>, ;TI"$has three rows and two columns:;To:RDoc::Markup::Verbatim;[I""foo,0\nbar,1\nbaz,2\n" ;T:@format0o; ;[I"ODespite the name \CSV, a \CSV representation can use different separators.;T@o; ;[ I"6For more about tables, see the Wikipedia article ;TI"Q"{Table (information)}[https://en.wikipedia.org/wiki/Table_(information)]", ;TI"especially its section ;TI"U"{Simple table}[https://en.wikipedia.org/wiki/Table_(information)#Simple_table]";T@S; ; i;I"\Class \CSV;T@o; ;[I"%Class \CSV provides methods for:;To;;;;[o;;0;[o; ;[I"\Parsing \CSV data from a \String object, a \File (via its file path), or an \IO object.;To;;0;[o; ;[I".Generating \CSV data to a \String object.;T@o; ;[I"To make \CSV available:;To;;[I"require 'csv' ;T;0o; ;[I"6All examples here assume that this has been done.;T@S; ; i;I"Keeping It Simple;T@o; ;[I"RA \CSV object has dozens of instance methods that offer fine-grained control ;TI"*of parsing and generating \CSV data. ;TI"8For many needs, though, simpler approaches will do.;T@o; ;[ I";This section summarizes the singleton methods in \CSV ;TI"=that allow you to parse and generate without explicitly ;TI"creating \CSV objects. ;TI"#For details, follow the links.;T@S; ; i;I"Simple Parsing;T@o; ;[I"/Parsing methods commonly return either of:;To;;;;[o;;0;[o; ;[I"$An \Array of Arrays of Strings:;To;;;;[o;;0;[o; ;[I",The outer \Array is the entire "table".;To;;0;[o; ;[I" Each inner \Array is a row.;To;;0;[o; ;[I"Each \String is a field.;To;;0;[o; ;[I",A CSV::Table object. For details, see ;TI"<{\CSV with Headers}[#class-CSV-label-CSV+with+Headers].;T@S; ; i ;I"Parsing a \String;T@o; ;[I",The input to be parsed can be a string:;To;;[I"&string = "foo,0\nbar,1\nbaz,2\n" ;T;0o; ;[I"4\Method CSV.parse returns the entire \CSV data:;To;;[I"GCSV.parse(string) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"7\Method CSV.parse_line returns only the first row:;To;;[I".CSV.parse_line(string) # => ["foo", "0"] ;T;0o; ;[I"G\CSV extends class \String with instance method String#parse_csv, ;TI"+which also returns only the first row:;To;;[I"(string.parse_csv # => ["foo", "0"] ;T;0S; ; i ;I"Parsing Via a \File Path;T@o; ;[I"-The input to be parsed can be in a file:;To;;[I"&string = "foo,0\nbar,1\nbaz,2\n" ;TI"path = 't.csv' ;TI"File.write(path, string) ;T;0o; ;[I"3\Method CSV.read returns the entire \CSV data:;To;;[I"DCSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"G\Method CSV.foreach iterates, passing each row to the given block:;To;;[I" CSV.foreach(path) do |row| ;TI" p row ;TI" end ;T;0o; ;[I"Output:;To;;[I"["foo", "0"] ;TI"["bar", "1"] ;TI"["baz", "2"] ;T;0o; ;[I"K\Method CSV.table returns the entire \CSV data as a CSV::Table object:;To;;[I"DCSV.table(path) # => #<CSV::Table mode:col_or_row row_count:3> ;T;0S; ; i ;I"$Parsing from an Open \IO Stream;T@o; ;[I"9The input to be parsed can be in an open \IO stream:;T@o; ;[I"3\Method CSV.read returns the entire \CSV data:;To;;[I"File.open(path) do |file| ;TI" CSV.read(file) ;TI"9end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"As does method CSV.parse:;To;;[I"File.open(path) do |file| ;TI" CSV.parse(file) ;TI"9end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"7\Method CSV.parse_line returns only the first row:;To;;[I"File.open(path) do |file| ;TI" CSV.parse_line(file) ;TI"end # => ["foo", "0"] ;T;0o; ;[I"G\Method CSV.foreach iterates, passing each row to the given block:;To;;[ I"File.open(path) do |file| ;TI"" CSV.foreach(file) do |row| ;TI" p row ;TI" end ;TI" end ;T;0o; ;[I"Output:;To;;[I"["foo", "0"] ;TI"["bar", "1"] ;TI"["baz", "2"] ;T;0o; ;[I"K\Method CSV.table returns the entire \CSV data as a CSV::Table object:;To;;[I"File.open(path) do |file| ;TI" CSV.table(file) ;TI"8end # => #<CSV::Table mode:col_or_row row_count:3> ;T;0S; ; i;I"Simple Generating;T@o; ;[I"-\Method CSV.generate returns a \String; ;TI"8this example uses method CSV#<< to append the rows ;TI"that are to be generated:;To;;[I"+output_string = CSV.generate do |csv| ;TI" csv << ['foo', 0] ;TI" csv << ['bar', 1] ;TI" csv << ['baz', 2] ;TI" end ;TI"0output_string # => "foo,0\nbar,1\nbaz,2\n" ;T;0o; ;[I"K\Method CSV.generate_line returns a \String containing the single row ;TI" constructed from an \Array:;To;;[I"4CSV.generate_line(['foo', '0']) # => "foo,0\n" ;T;0o; ;[I"K\CSV extends class \Array with instance method <tt>Array#to_csv</tt>, ;TI"*which forms an \Array into a \String:;To;;[I"(['foo', '0'].to_csv # => "foo,0\n" ;T;0S; ; i;I""Filtering" \CSV;T@o; ;[I"D\Method CSV.filter provides a Unix-style filter for \CSV data. ;TI"9The input data is processed to form the output data:;To;;[I")in_string = "foo,0\nbar,1\nbaz,2\n" ;TI"out_string = '' ;TI"0CSV.filter(in_string, out_string) do |row| ;TI" row[0] = row[0].upcase ;TI" row[1] *= 4 ;TI" end ;TI"6out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n" ;T;0S; ; i;I"\CSV Objects;T@o; ;[I"2There are three ways to create a \CSV object:;To;;;;[o;;0;[o; ;[I"/\Method CSV.new returns a new \CSV object.;To;;0;[o; ;[I">\Method CSV.instance returns a new or cached \CSV object.;To;;0;[o; ;[I"=\Method \CSV() also returns a new or cached \CSV object.;T@S; ; i;I"Instance Methods;T@o; ;[I"/\CSV has three groups of instance methods:;To;;;;[o;;0;[o; ;[I"1Its own internally defined instance methods.;To;;0;[o; ;[I"+Methods included by module Enumerable.;To;;0;[o; ;[I".Methods delegated to class IO. See below.;T@S; ; i ;I"Delegated Methods;T@o; ;[I"NFor convenience, a CSV object will delegate to many methods in class IO. ;TI"=(A few have wrapper "guard code" in \CSV.) You may call:;To;;;;[&o;;0;[o; ;[I"IO#binmode;To;;0;[o; ;[I"#binmode?;To;;0;[o; ;[I" IO#close;To;;0;[o; ;[I"IO#close_read;To;;0;[o; ;[I"IO#close_write;To;;0;[o; ;[I"IO#closed?;To;;0;[o; ;[I" #eof;To;;0;[o; ;[I" #eof?;To;;0;[o; ;[I"IO#external_encoding;To;;0;[o; ;[I" IO#fcntl;To;;0;[o; ;[I"IO#fileno;To;;0;[o; ;[I"#flock;To;;0;[o; ;[I" IO#flush;To;;0;[o; ;[I" IO#fsync;To;;0;[o; ;[I"IO#internal_encoding;To;;0;[o; ;[I"#ioctl;To;;0;[o; ;[I"IO#isatty;To;;0;[o; ;[I" #path;To;;0;[o; ;[I"IO#pid;To;;0;[o; ;[I"IO#pos;To;;0;[o; ;[I"IO#pos=;To;;0;[o; ;[I"IO#reopen;To;;0;[o; ;[I"#rewind;To;;0;[o; ;[I"IO#seek;To;;0;[o; ;[I" #stat;To;;0;[o; ;[I"IO#string;To;;0;[o; ;[I"IO#sync;To;;0;[o; ;[I" IO#sync=;To;;0;[o; ;[I"IO#tell;To;;0;[o; ;[I" #to_i;To;;0;[o; ;[I"#to_io;To;;0;[o; ;[I"IO#truncate;To;;0;[o; ;[I"IO#tty?;T@S; ; i;I"Options;T@o; ;[I"(The default values for options are:;To;;[I"DEFAULT_OPTIONS = { ;TI"* # For both parsing and generating. ;TI" col_sep: ",", ;TI"" row_sep: :auto, ;TI" quote_char: '"', ;TI" # For parsing. ;TI" field_size_limit: nil, ;TI" converters: nil, ;TI" unconverted_fields: nil, ;TI"" headers: false, ;TI"" return_headers: false, ;TI" header_converters: nil, ;TI"" skip_blanks: false, ;TI" skip_lines: nil, ;TI"" liberal_parsing: false, ;TI" nil_value: nil, ;TI" empty_value: "", ;TI"" strip: false, ;TI" # For generating. ;TI" write_headers: nil, ;TI"! quote_empty: true, ;TI"" force_quotes: false, ;TI" write_converters: nil, ;TI" write_nil_value: nil, ;TI" write_empty_value: "", ;TI"} ;T;0S; ; i ;I"Options for Parsing;T@o; ;[I"=Options for parsing, described in detail below, include:;To;;;;[o;;0;[o; ;[I"B+row_sep+: Specifies the row separator; used to delimit rows.;To;;0;[o; ;[I"G+col_sep+: Specifies the column separator; used to delimit fields.;To;;0;[o; ;[I"G+quote_char+: Specifies the quote character; used to quote fields.;To;;0;[o; ;[I"G+field_size_limit+: Specifies the maximum field size + 1 allowed. ;TI":Deprecated since 3.2.3. Use +max_field_size+ instead.;To;;0;[o; ;[I"@+max_field_size+: Specifies the maximum field size allowed.;To;;0;[o; ;[I"=+converters+: Specifies the field converters to be used.;To;;0;[o; ;[I"T+unconverted_fields+: Specifies whether unconverted fields are to be available.;To;;0;[o; ;[I"9+headers+: Specifies whether data contains headers, ;TI")or specifies the headers themselves.;To;;0;[o; ;[I"D+return_headers+: Specifies whether headers are to be returned.;To;;0;[o; ;[I"E+header_converters+: Specifies the header converters to be used.;To;;0;[o; ;[I"E+skip_blanks+: Specifies whether blanks lines are to be ignored.;To;;0;[o; ;[I"E+skip_lines+: Specifies how comments lines are to be recognized.;To;;0;[o; ;[I"J+strip+: Specifies whether leading and trailing whitespace are to be ;TI"Qstripped from fields. This must be compatible with +col_sep+; if it is not, ;TI"6then an +ArgumentError+ exception will be raised.;To;;0;[o; ;[I"G+liberal_parsing+: Specifies whether \CSV should attempt to parse ;TI"non-compliant data.;To;;0;[o; ;[I"_+nil_value+: Specifies the object that is to be substituted for each null (no-text) field.;To;;0;[o; ;[I"X+empty_value+: Specifies the object that is to be substituted for each empty field.;T@S; ; i;I"Option +row_sep+;T@o; ;[I"WSpecifies the row separator, a \String or the \Symbol <tt>:auto</tt> (see below), ;TI"0to be used for both parsing and generating.;T@o; ;[I"Default value:;To;;[I"5CSV::DEFAULT_OPTIONS.fetch(:row_sep) # => :auto ;T;0S:RDoc::Markup::Rule:weighti@o; ;[I"JWhen +row_sep+ is a \String, that \String becomes the row separator. ;TI"GThe String will be transcoded into the data's Encoding before use.;T@o; ;[I"Using <tt>"\n"</tt>:;To;;[I"row_sep = "\n" ;TI"3str = CSV.generate(row_sep: row_sep) do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"&str # => "foo,0\nbar,1\nbaz,2\n" ;TI"ary = CSV.parse(str) ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"Using <tt>|</tt> (pipe):;To;;[I"row_sep = '|' ;TI"3str = CSV.generate(row_sep: row_sep) do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"#str # => "foo,0|bar,1|baz,2|" ;TI",ary = CSV.parse(str, row_sep: row_sep) ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"%Using <tt>--</tt> (two hyphens):;To;;[I"row_sep = '--' ;TI"3str = CSV.generate(row_sep: row_sep) do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"&str # => "foo,0--bar,1--baz,2--" ;TI",ary = CSV.parse(str, row_sep: row_sep) ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"&Using <tt>''</tt> (empty string):;To;;[I"row_sep = '' ;TI"3str = CSV.generate(row_sep: row_sep) do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI" str # => "foo,0bar,1baz,2" ;TI",ary = CSV.parse(str, row_sep: row_sep) ;TI"-ary # => [["foo", "0bar", "1baz", "2"]] ;T;0S;;i@o; ;[I":When +row_sep+ is the \Symbol +:auto+ (the default), ;TI"8generating uses <tt>"\n"</tt> as the row separator:;To;;[I"!str = CSV.generate do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"&str # => "foo,0\nbar,1\nbaz,2\n" ;T;0o; ;[I"MParsing, on the other hand, invokes auto-discovery of the row separator.;T@o; ;[I"hAuto-discovery reads ahead in the data looking for the next <tt>\r\n</tt>, +\n+, or +\r+ sequence. ;TI"HThe sequence will be selected even if it occurs in a quoted field, ;TI">assuming that you would have the same line endings there.;T@o; ;[I" Example:;To;;[ I"!str = CSV.generate do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"&str # => "foo,0\nbar,1\nbaz,2\n" ;TI"ary = CSV.parse(str) ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"HThe default <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>) is used ;TI"%if any of the following is true:;To;;;;[o;;0;[o; ;[I"&None of those sequences is found.;To;;0;[o; ;[I"4Data is +ARGF+, +STDIN+, +STDOUT+, or +STDERR+.;To;;0;[o; ;[I"-The stream is only available for output.;T@o; ;[I"-Obviously, discovery takes a little time. Set manually if speed is important. Also note that IO objects should be opened in binary mode on Windows if this feature will be used as the line-ending translation can cause problems with resetting the document position to where it was before the read ahead.;T@S; ; i;I"Option +col_sep+;T@o; ;[I"6Specifies the \String field separator to be used ;TI"&for both parsing and generating. ;TI"IThe \String will be transcoded into the data's \Encoding before use.;T@o; ;[I"Default value:;To;;[I";CSV::DEFAULT_OPTIONS.fetch(:col_sep) # => "," (comma) ;T;0o; ;[I"Using the default (comma):;To;;[ I"!str = CSV.generate do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"&str # => "foo,0\nbar,1\nbaz,2\n" ;TI"ary = CSV.parse(str) ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"Using +:+ (colon):;To;;[I"col_sep = ':' ;TI"3str = CSV.generate(col_sep: col_sep) do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"&str # => "foo:0\nbar:1\nbaz:2\n" ;TI",ary = CSV.parse(str, col_sep: col_sep) ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"Using +::+ (two colons):;To;;[I"col_sep = '::' ;TI"3str = CSV.generate(col_sep: col_sep) do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI")str # => "foo::0\nbar::1\nbaz::2\n" ;TI",ary = CSV.parse(str, col_sep: col_sep) ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"&Using <tt>''</tt> (empty string):;To;;[I"col_sep = '' ;TI"3str = CSV.generate(col_sep: col_sep) do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"#str # => "foo0\nbar1\nbaz2\n" ;T;0S;;i@o; ;[I";Raises an exception if parsing with the empty \String:;To;;[I"col_sep = '' ;TI"H# Raises ArgumentError (:col_sep must be 1 or more characters: "") ;TI"7CSV.parse("foo0\nbar1\nbaz2\n", col_sep: col_sep) ;T;0S; ; i;I"Option +quote_char+;T@o; ;[I"MSpecifies the character (\String of length 1) used used to quote fields ;TI"%in both parsing and generating. ;TI"IThis String will be transcoded into the data's \Encoding before use.;T@o; ;[I"Default value:;To;;[I"FCSV::DEFAULT_OPTIONS.fetch(:quote_char) # => "\"" (double quote) ;T;0o; ;[I"WThis is useful for an application that incorrectly uses <tt>'</tt> (single-quote) ;TI"Gto quote fields, instead of the correct <tt>"</tt> (double-quote).;T@o; ;[I"&Using the default (double quote):;To;;[ I"!str = CSV.generate do |csv| ;TI" csv << ['foo', 0] ;TI" csv << ["'bar'", 1] ;TI" csv << ['"baz"', 2] ;TI" end ;TI"4str # => "foo,0\n'bar',1\n\"\"\"baz\"\"\",2\n" ;TI"ary = CSV.parse(str) ;TI"?ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]] ;T;0o; ;[I"%Using <tt>'</tt> (single-quote):;To;;[I"quote_char = "'" ;TI"9str = CSV.generate(quote_char: quote_char) do |csv| ;TI" csv << ['foo', 0] ;TI" csv << ["'bar'", 1] ;TI" csv << ['"baz"', 2] ;TI" end ;TI"0str # => "foo,0\n'''bar''',1\n\"baz\",2\n" ;TI"2ary = CSV.parse(str, quote_char: quote_char) ;TI"?ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]] ;T;0S;;i@o; ;[I"ARaises an exception if the \String length is greater than 1:;To;;[I"U# Raises ArgumentError (:quote_char has to be nil or a single character String) ;TI"#CSV.new('', quote_char: 'xx') ;T;0o; ;[I"7Raises an exception if the value is not a \String:;To;;[I"U# Raises ArgumentError (:quote_char has to be nil or a single character String) ;TI"#CSV.new('', quote_char: :foo) ;T;0S; ; i;I"Option +field_size_limit+;T@o; ;[I"-Specifies the \Integer field size limit.;T@o; ;[I"Default value:;To;;[I"<CSV::DEFAULT_OPTIONS.fetch(:field_size_limit) # => nil ;T;0o; ;[I"[This is a maximum size CSV will read ahead looking for the closing quote for a field. ;TI"E(In truth, it reads to the first line ending beyond this size.) ;TI"UIf a quote cannot be found within the limit CSV will raise a MalformedCSVError, ;TI""assuming the data is faulty. ;TI"WYou can use this limit to prevent what are effectively DoS attacks on the parser. ;TI"?However, this limit can cause a legitimate parse to fail; ;TI"5therefore the default value is +nil+ (no limit).;T@o; ;[I"&For the examples in this section:;To;;[I"str = <<~EOT ;TI" "a","b" ;TI" " ;TI" 2345 ;TI" ","" ;TI" EOT ;TI"1str # => "\"a\",\"b\"\n\"\n2345\n\",\"\"\n" ;T;0o; ;[I"Using the default +nil+:;To;;[I"ary = CSV.parse(str) ;TI"-ary # => [["a", "b"], ["\n2345\n", ""]] ;T;0o; ;[I"Using <tt>50</tt>:;To;;[I"field_size_limit = 50 ;TI">ary = CSV.parse(str, field_size_limit: field_size_limit) ;TI"-ary # => [["a", "b"], ["\n2345\n", ""]] ;T;0S;;i@o; ;[I"0Raises an exception if a field is too long:;To;;[I"$big_str = "123456789\n" * 1024 ;TI"F# Raises CSV::MalformedCSVError (Field size exceeded in line 1.) ;TI"ICSV.parse('valid,fields,"' + big_str + '"', field_size_limit: 2048) ;T;0S; ; i;I"Option +converters+;T@o; ;[I"8Specifies converters to be used in parsing fields. ;TI">See {Field Converters}[#class-CSV-label-Field+Converters];T@o; ;[I"Default value:;To;;[I"6CSV::DEFAULT_OPTIONS.fetch(:converters) # => nil ;T;0o; ;[I"-The value may be a field converter name ;TI"C(see {Stored Converters}[#class-CSV-label-Stored+Converters]):;To;;[I"str = '1,2,3' ;TI"# Without a converter ;TI"!array = CSV.parse_line(str) ;TI" array # => ["1", "2", "3"] ;TI"(# With built-in converter :integer ;TI"7array = CSV.parse_line(str, converters: :integer) ;TI"array # => [1, 2, 3] ;T;0o; ;[I"'The value may be a converter list ;TI"?(see {Converter Lists}[#class-CSV-label-Converter+Lists]):;To;;[I"str = '1,3.14159' ;TI"# Without converters ;TI"!array = CSV.parse_line(str) ;TI"!array # => ["1", "3.14159"] ;TI" # With built-in converters ;TI"Aarray = CSV.parse_line(str, converters: [:integer, :float]) ;TI"array # => [1, 3.14159] ;T;0o; ;[I"0The value may be a \Proc custom converter: ;TI"O(see {Custom Field Converters}[#class-CSV-label-Custom+Field+Converters]):;To;;[I"$str = ' foo , bar , baz ' ;TI"# Without a converter ;TI"!array = CSV.parse_line(str) ;TI"1array # => [" foo ", " bar ", " baz "] ;TI"# With a custom converter ;TI"Jarray = CSV.parse_line(str, converters: proc {|field| field.strip }) ;TI"&array # => ["foo", "bar", "baz"] ;T;0o; ;[I"QSee also {Custom Field Converters}[#class-CSV-label-Custom+Field+Converters];T@S;;i@o; ;[I"MRaises an exception if the converter is not a converter name or a \Proc:;To;;[I"str = 'foo,0' ;TI"H# Raises NoMethodError (undefined method `arity' for nil:NilClass) ;TI"&CSV.parse(str, converters: :foo) ;T;0S; ; i;I" Option +unconverted_fields+;T@o; ;[I"`Specifies the boolean that determines whether unconverted field values are to be available.;T@o; ;[I"Default value:;To;;[I">CSV::DEFAULT_OPTIONS.fetch(:unconverted_fields) # => nil ;T;0o; ;[I"FThe unconverted field values are those found in the source data, ;TI"@prior to any conversions performed via option +converters+.;T@o; ;[I"1When option +unconverted_fields+ is +true+, ;TI"Beach returned row (\Array or \CSV::Row) has an added method, ;TI"E+unconverted_fields+, that returns the unconverted field values:;To;;[I"str = <<-EOT ;TI"foo,0 ;TI"bar,1 ;TI"baz,2 ;TI" EOT ;TI""# Without unconverted_fields ;TI"0csv = CSV.parse(str, converters: :integer) ;TI"3csv # => [["foo", 0], ["bar", 1], ["baz", 2]] ;TI";csv.first.respond_to?(:unconverted_fields) # => false ;TI"# With unconverted_fields ;TI"Jcsv = CSV.parse(str, converters: :integer, unconverted_fields: true) ;TI"3csv # => [["foo", 0], ["bar", 1], ["baz", 2]] ;TI":csv.first.respond_to?(:unconverted_fields) # => true ;TI"4csv.first.unconverted_fields # => ["foo", "0"] ;T;0S; ; i;I"Option +headers+;T@o; ;[I"ASpecifies a boolean, \Symbol, \Array, or \String to be used ;TI"to define column headers.;T@o; ;[I"Default value:;To;;[I"5CSV::DEFAULT_OPTIONS.fetch(:headers) # => false ;T;0S;;i@o; ;[I"Without +headers+:;To;;[I"str = <<-EOT ;TI"Name,Count ;TI"foo,0 ;TI"bar,1 ;TI"bax,2 ;TI" EOT ;TI"csv = CSV.new(str) ;TI"gcsv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\""> ;TI"csv.headers # => nil ;TI"&csv.shift # => ["Name", "Count"] ;T;0S;;i@o; ;[I"3If set to +true+ or the \Symbol +:first_row+, ;TI">the first row of the data is treated as a row of headers:;To;;[I"str = <<-EOT ;TI"Name,Count ;TI"foo,0 ;TI"bar,1 ;TI"bax,2 ;TI" EOT ;TI"'csv = CSV.new(str, headers: true) ;TI"|csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:2 col_sep:"," row_sep:"\n" quote_char:"\"" headers:["Name", "Count"]> ;TI"(csv.headers # => ["Name", "Count"] ;TI"9csv.shift # => #<CSV::Row "Name":"bar" "Count":"1"> ;T;0S;;i@o; ;[I"EIf set to an \Array, the \Array elements are treated as headers:;To;;[I"str = <<-EOT ;TI"foo,0 ;TI"bar,1 ;TI"bax,2 ;TI" EOT ;TI"4csv = CSV.new(str, headers: ['Name', 'Count']) ;TI" csv ;TI"(csv.headers # => ["Name", "Count"] ;TI"9csv.shift # => #<CSV::Row "Name":"bar" "Count":"1"> ;T;0S;;i@o; ;[I"XIf set to a \String +str+, method <tt>CSV::parse_line(str, options)</tt> is called ;TI"Owith the current +options+, and the returned \Array is treated as headers:;To;;[I"str = <<-EOT ;TI"foo,0 ;TI"bar,1 ;TI"bax,2 ;TI" EOT ;TI"/csv = CSV.new(str, headers: 'Name,Count') ;TI" csv ;TI"(csv.headers # => ["Name", "Count"] ;TI"9csv.shift # => #<CSV::Row "Name":"bar" "Count":"1"> ;T;0S; ; i;I"Option +return_headers+;T@o; ;[I"ASpecifies the boolean that determines whether method #shift ;TI"'returns or ignores the header row.;T@o; ;[I"Default value:;To;;[I"<CSV::DEFAULT_OPTIONS.fetch(:return_headers) # => false ;T;0o; ;[I"Examples:;To;;[I"str = <<-EOT ;TI"Name,Count ;TI"foo,0 ;TI"bar,1 ;TI"bax,2 ;TI" EOT ;TI"0# Without return_headers first row is str. ;TI"'csv = CSV.new(str, headers: true) ;TI"9csv.shift # => #<CSV::Row "Name":"foo" "Count":"0"> ;TI"1# With return_headers first row is headers. ;TI"=csv = CSV.new(str, headers: true, return_headers: true) ;TI">csv.shift # => #<CSV::Row "Name":"Name" "Count":"Count"> ;T;0S; ; i;I"Option +header_converters+;T@o; ;[I"9Specifies converters to be used in parsing headers. ;TI"@See {Header Converters}[#class-CSV-label-Header+Converters];T@o; ;[I"Default value:;To;;[I"=CSV::DEFAULT_OPTIONS.fetch(:header_converters) # => nil ;T;0o; ;[I"[Identical in functionality to option {converters}[#class-CSV-label-Option+converters] ;TI"except that:;To;;;;[o;;0;[o; ;[I"1The converters apply only to the header row.;To;;0;[o; ;[I"BThe built-in header converters are +:downcase+ and +:symbol+.;T@o; ;[I"-This section assumes prior execution of:;To;;[I"str = <<-EOT ;TI"Name,Value ;TI"foo,0 ;TI"bar,1 ;TI"baz,2 ;TI" EOT ;TI" # With no header converter ;TI"+table = CSV.parse(str, headers: true) ;TI"*table.headers # => ["Name", "Value"] ;T;0o; ;[I".The value may be a header converter name ;TI"C(see {Stored Converters}[#class-CSV-label-Stored+Converters]):;To;;[I"Itable = CSV.parse(str, headers: true, header_converters: :downcase) ;TI"*table.headers # => ["name", "value"] ;T;0o; ;[I"'The value may be a converter list ;TI"?(see {Converter Lists}[#class-CSV-label-Converter+Lists]):;To;;[I".header_converters = [:downcase, :symbol] ;TI"Qtable = CSV.parse(str, headers: true, header_converters: header_converters) ;TI"(table.headers # => [:name, :value] ;T;0o; ;[I"/The value may be a \Proc custom converter ;TI"Q(see {Custom Header Converters}[#class-CSV-label-Custom+Header+Converters]):;To;;[I"5upcase_converter = proc {|field| field.upcase } ;TI"Ptable = CSV.parse(str, headers: true, header_converters: upcase_converter) ;TI"*table.headers # => ["NAME", "VALUE"] ;T;0o; ;[I"SSee also {Custom Header Converters}[#class-CSV-label-Custom+Header+Converters];T@S; ; i;I"Option +skip_blanks+;T@o; ;[I"[Specifies a boolean that determines whether blank lines in the input will be ignored; ;TI"Ka line that contains a column separator is not considered to be blank.;T@o; ;[I"Default value:;To;;[I"9CSV::DEFAULT_OPTIONS.fetch(:skip_blanks) # => false ;T;0o; ;[I"ESee also option {skiplines}[#class-CSV-label-Option+skip_lines].;T@o; ;[I""For examples in this section:;To;;[ I"str = <<-EOT ;TI"foo,0 ;TI" ;TI"bar,1 ;TI"baz,2 ;TI" ;TI", ;TI" EOT ;T;0o; ;[I" Using the default, +false+:;To;;[I"ary = CSV.parse(str) ;TI"Mary # => [["foo", "0"], [], ["bar", "1"], ["baz", "2"], [], [nil, nil]] ;T;0o; ;[I"Using +true+:;To;;[I"-ary = CSV.parse(str, skip_blanks: true) ;TI"Eary # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]] ;T;0o; ;[I"Using a truthy value:;To;;[I"-ary = CSV.parse(str, skip_blanks: :foo) ;TI"Eary # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]] ;T;0S; ; i;I"Option +skip_lines+;T@o; ;[I"aSpecifies an object to use in identifying comment lines in the input that are to be ignored:;To;;;;[o;;0;[o; ;[I"/If a \Regexp, ignores lines that match it.;To;;0;[o; ;[I"IIf a \String, converts it to a \Regexp, ignores lines that match it.;To;;0;[o; ;[I"6If +nil+, no lines are considered to be comments.;T@o; ;[I"Default value:;To;;[I"6CSV::DEFAULT_OPTIONS.fetch(:skip_lines) # => nil ;T;0o; ;[I""For examples in this section:;To;;[ I"str = <<-EOT ;TI"# Comment ;TI"foo,0 ;TI"bar,1 ;TI"baz,2 ;TI"# Another comment ;TI" EOT ;TI"Dstr # => "# Comment\nfoo,0\nbar,1\nbaz,2\n# Another comment\n" ;T;0o; ;[I"Using the default, +nil+:;To;;[I"ary = CSV.parse(str) ;TI"_ary # => [["# Comment"], ["foo", "0"], ["bar", "1"], ["baz", "2"], ["# Another comment"]] ;T;0o; ;[I"Using a \Regexp:;To;;[I",ary = CSV.parse(str, skip_lines: /^#/) ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"Using a \String:;To;;[I"+ary = CSV.parse(str, skip_lines: '#') ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0S;;i@o; ;[I"WRaises an exception if given an object that is not a \Regexp, a \String, or +nil+:;To;;[I"F# Raises ArgumentError (:skip_lines has to respond to #match: 0) ;TI"#CSV.parse(str, skip_lines: 0) ;T;0S; ; i;I"Option +strip+;T@o; ;[I"9Specifies the boolean value that determines whether ;TI"2whitespace is stripped from each input field.;T@o; ;[I"Default value:;To;;[I"3CSV::DEFAULT_OPTIONS.fetch(:strip) # => false ;T;0o; ;[I" With default value +false+:;To;;[I"%ary = CSV.parse_line(' a , b ') ;TI"ary # => [" a ", " b "] ;T;0o; ;[I"With value +true+:;To;;[I"2ary = CSV.parse_line(' a , b ', strip: true) ;TI"ary # => ["a", "b"] ;T;0S; ; i;I"Option +liberal_parsing+;T@o; ;[I"ASpecifies the boolean or hash value that determines whether ;TI"CCSV will attempt to parse input not conformant with RFC 4180, ;TI".such as double quotes in unquoted fields.;T@o; ;[I"Default value:;To;;[I"=CSV::DEFAULT_OPTIONS.fetch(:liberal_parsing) # => false ;T;0o; ;[I"For the next two examples:;To;;[I"-str = 'is,this "three, or four",fields' ;T;0o; ;[I"Without +liberal_parsing+:;To;;[I"A# Raises CSV::MalformedCSVError (Illegal quoting in str 1.) ;TI"CSV.parse_line(str) ;T;0o; ;[I"With +liberal_parsing+:;To;;[I"6ary = CSV.parse_line(str, liberal_parsing: true) ;TI"=ary # => ["is", "this \"three", " or four\"", "fields"] ;T;0o; ;[ I"CUse the +backslash_quote+ sub-option to parse values that use ;TI";a backslash to escape a double-quote character. This ;TI">causes the parser to treat <code>\"</code> as if it were ;TI"<code>""</code>.;T@o; ;[I"For the next two examples:;To;;[I"Qstr = 'Show,"Harry \"Handcuff\" Houdini, the one and only","Tampa Theater"' ;T;0o; ;[I"JWith +liberal_parsing+, but without the +backslash_quote+ sub-option:;To;;[ I"l# Incorrect interpretation of backslash; incorrectly interprets the quoted comma as a field separator. ;TI"6ary = CSV.parse_line(str, liberal_parsing: true) ;TI"cary # => ["Show", "\"Harry \\\"Handcuff\\\" Houdini", " the one and only\"", "Tampa Theater"] ;TI"2puts ary[1] # => "Harry \"Handcuff\" Houdini ;T;0o; ;[I"AWith +liberal_parsing+ and its +backslash_quote+ sub-option:;To;;[I"Kary = CSV.parse_line(str, liberal_parsing: { backslash_quote: true }) ;TI"Xary # => ["Show", "Harry \"Handcuff\" Houdini, the one and only", "Tampa Theater"] ;TI"Aputs ary[1] # => Harry "Handcuff" Houdini, the one and only ;T;0S; ; i;I"Option +nil_value+;T@o; ;[I"RSpecifies the object that is to be substituted for each null (no-text) field.;T@o; ;[I"Default value:;To;;[I"5CSV::DEFAULT_OPTIONS.fetch(:nil_value) # => nil ;T;0o; ;[I"With the default, +nil+:;To;;[I">CSV.parse_line('a,,b,,c') # => ["a", nil, "b", nil, "c"] ;T;0o; ;[I"With a different object:;To;;[I"HCSV.parse_line('a,,b,,c', nil_value: 0) # => ["a", 0, "b", 0, "c"] ;T;0S; ; i;I"Option +empty_value+;T@o; ;[I"4Specifies the object that is to be substituted ;TI".for each field that has an empty \String.;T@o; ;[I"Default value:;To;;[I"ECSV::DEFAULT_OPTIONS.fetch(:empty_value) # => "" (empty string) ;T;0o; ;[I"#With the default, <tt>""</tt>:;To;;[I"@CSV.parse_line('a,"",b,"",c') # => ["a", "", "b", "", "c"] ;T;0o; ;[I"With a different object:;To;;[I"TCSV.parse_line('a,"",b,"",c', empty_value: 'x') # => ["a", "x", "b", "x", "c"] ;T;0S; ; i ;I"Options for Generating;T@o; ;[I"@Options for generating, described in detail below, include:;To;;;;[o;;0;[o; ;[I"B+row_sep+: Specifies the row separator; used to delimit rows.;To;;0;[o; ;[I"G+col_sep+: Specifies the column separator; used to delimit fields.;To;;0;[o; ;[I"G+quote_char+: Specifies the quote character; used to quote fields.;To;;0;[o; ;[I"B+write_headers+: Specifies whether headers are to be written.;To;;0;[o; ;[I"I+force_quotes+: Specifies whether each output field is to be quoted.;To;;0;[o; ;[I"N+quote_empty+: Specifies whether each empty output field is to be quoted.;To;;0;[o; ;[I"N+write_converters+: Specifies the field converters to be used in writing.;To;;0;[o; ;[I"c+write_nil_value+: Specifies the object that is to be substituted for each +nil+-valued field.;To;;0;[o; ;[I"^+write_empty_value+: Specifies the object that is to be substituted for each empty field.;T@S; ; i;I"Option +row_sep+;T@o; ;[I"WSpecifies the row separator, a \String or the \Symbol <tt>:auto</tt> (see below), ;TI"0to be used for both parsing and generating.;T@o; ;[I"Default value:;To;;[I"5CSV::DEFAULT_OPTIONS.fetch(:row_sep) # => :auto ;T;0S;;i@o; ;[I"JWhen +row_sep+ is a \String, that \String becomes the row separator. ;TI"GThe String will be transcoded into the data's Encoding before use.;T@o; ;[I"Using <tt>"\n"</tt>:;To;;[I"row_sep = "\n" ;TI"3str = CSV.generate(row_sep: row_sep) do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"&str # => "foo,0\nbar,1\nbaz,2\n" ;TI"ary = CSV.parse(str) ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"Using <tt>|</tt> (pipe):;To;;[I"row_sep = '|' ;TI"3str = CSV.generate(row_sep: row_sep) do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"#str # => "foo,0|bar,1|baz,2|" ;TI",ary = CSV.parse(str, row_sep: row_sep) ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"%Using <tt>--</tt> (two hyphens):;To;;[I"row_sep = '--' ;TI"3str = CSV.generate(row_sep: row_sep) do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"&str # => "foo,0--bar,1--baz,2--" ;TI",ary = CSV.parse(str, row_sep: row_sep) ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"&Using <tt>''</tt> (empty string):;To;;[I"row_sep = '' ;TI"3str = CSV.generate(row_sep: row_sep) do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI" str # => "foo,0bar,1baz,2" ;TI",ary = CSV.parse(str, row_sep: row_sep) ;TI"-ary # => [["foo", "0bar", "1baz", "2"]] ;T;0S;;i@o; ;[I":When +row_sep+ is the \Symbol +:auto+ (the default), ;TI"8generating uses <tt>"\n"</tt> as the row separator:;To;;[I"!str = CSV.generate do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"&str # => "foo,0\nbar,1\nbaz,2\n" ;T;0o; ;[I"MParsing, on the other hand, invokes auto-discovery of the row separator.;T@o; ;[I"hAuto-discovery reads ahead in the data looking for the next <tt>\r\n</tt>, +\n+, or +\r+ sequence. ;TI"HThe sequence will be selected even if it occurs in a quoted field, ;TI">assuming that you would have the same line endings there.;T@o; ;[I" Example:;To;;[ I"!str = CSV.generate do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"&str # => "foo,0\nbar,1\nbaz,2\n" ;TI"ary = CSV.parse(str) ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"HThe default <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>) is used ;TI"%if any of the following is true:;To;;;;[o;;0;[o; ;[I"&None of those sequences is found.;To;;0;[o; ;[I"4Data is +ARGF+, +STDIN+, +STDOUT+, or +STDERR+.;To;;0;[o; ;[I"-The stream is only available for output.;T@o; ;[I"-Obviously, discovery takes a little time. Set manually if speed is important. Also note that IO objects should be opened in binary mode on Windows if this feature will be used as the line-ending translation can cause problems with resetting the document position to where it was before the read ahead.;T@S; ; i;I"Option +col_sep+;T@o; ;[I"6Specifies the \String field separator to be used ;TI"&for both parsing and generating. ;TI"IThe \String will be transcoded into the data's \Encoding before use.;T@o; ;[I"Default value:;To;;[I";CSV::DEFAULT_OPTIONS.fetch(:col_sep) # => "," (comma) ;T;0o; ;[I"Using the default (comma):;To;;[ I"!str = CSV.generate do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"&str # => "foo,0\nbar,1\nbaz,2\n" ;TI"ary = CSV.parse(str) ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"Using +:+ (colon):;To;;[I"col_sep = ':' ;TI"3str = CSV.generate(col_sep: col_sep) do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"&str # => "foo:0\nbar:1\nbaz:2\n" ;TI",ary = CSV.parse(str, col_sep: col_sep) ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"Using +::+ (two colons):;To;;[I"col_sep = '::' ;TI"3str = CSV.generate(col_sep: col_sep) do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI")str # => "foo::0\nbar::1\nbaz::2\n" ;TI",ary = CSV.parse(str, col_sep: col_sep) ;TI"9ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"&Using <tt>''</tt> (empty string):;To;;[I"col_sep = '' ;TI"3str = CSV.generate(col_sep: col_sep) do |csv| ;TI" csv << [:foo, 0] ;TI" csv << [:bar, 1] ;TI" csv << [:baz, 2] ;TI" end ;TI"#str # => "foo0\nbar1\nbaz2\n" ;T;0S;;i@o; ;[I";Raises an exception if parsing with the empty \String:;To;;[I"col_sep = '' ;TI"H# Raises ArgumentError (:col_sep must be 1 or more characters: "") ;TI"7CSV.parse("foo0\nbar1\nbaz2\n", col_sep: col_sep) ;T;0S; ; i;I"Option +quote_char+;T@o; ;[I"MSpecifies the character (\String of length 1) used used to quote fields ;TI"%in both parsing and generating. ;TI"IThis String will be transcoded into the data's \Encoding before use.;T@o; ;[I"Default value:;To;;[I"FCSV::DEFAULT_OPTIONS.fetch(:quote_char) # => "\"" (double quote) ;T;0o; ;[I"WThis is useful for an application that incorrectly uses <tt>'</tt> (single-quote) ;TI"Gto quote fields, instead of the correct <tt>"</tt> (double-quote).;T@o; ;[I"&Using the default (double quote):;To;;[ I"!str = CSV.generate do |csv| ;TI" csv << ['foo', 0] ;TI" csv << ["'bar'", 1] ;TI" csv << ['"baz"', 2] ;TI" end ;TI"4str # => "foo,0\n'bar',1\n\"\"\"baz\"\"\",2\n" ;TI"ary = CSV.parse(str) ;TI"?ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]] ;T;0o; ;[I"%Using <tt>'</tt> (single-quote):;To;;[I"quote_char = "'" ;TI"9str = CSV.generate(quote_char: quote_char) do |csv| ;TI" csv << ['foo', 0] ;TI" csv << ["'bar'", 1] ;TI" csv << ['"baz"', 2] ;TI" end ;TI"0str # => "foo,0\n'''bar''',1\n\"baz\",2\n" ;TI"2ary = CSV.parse(str, quote_char: quote_char) ;TI"?ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]] ;T;0S;;i@o; ;[I"ARaises an exception if the \String length is greater than 1:;To;;[I"U# Raises ArgumentError (:quote_char has to be nil or a single character String) ;TI"#CSV.new('', quote_char: 'xx') ;T;0o; ;[I"7Raises an exception if the value is not a \String:;To;;[I"U# Raises ArgumentError (:quote_char has to be nil or a single character String) ;TI"#CSV.new('', quote_char: :foo) ;T;0S; ; i;I"Option +write_headers+;T@o; ;[I"[Specifies the boolean that determines whether a header row is included in the output; ;TI"%ignored if there are no headers.;T@o; ;[I"Default value:;To;;[I"9CSV::DEFAULT_OPTIONS.fetch(:write_headers) # => nil ;T;0o; ;[I"Without +write_headers+:;To;;[I"file_path = 't.csv' ;TI"CSV.open(file_path,'w', ;TI"& :headers => ['Name','Value'] ;TI" ) do |csv| ;TI" csv << ['foo', '0'] ;TI" end ;TI""CSV.open(file_path) do |csv| ;TI" csv.shift ;TI"end # => ["foo", "0"] ;T;0o; ;[I"With +write_headers+":;To;;[I"CSV.open(file_path,'w', ;TI"! :write_headers => true, ;TI"& :headers => ['Name','Value'] ;TI" ) do |csv| ;TI" csv << ['foo', '0'] ;TI" end ;TI""CSV.open(file_path) do |csv| ;TI" csv.shift ;TI" end # => ["Name", "Value"] ;T;0S; ; i;I"Option +force_quotes+;T@o; ;[I"\Specifies the boolean that determines whether each output field is to be double-quoted.;T@o; ;[I"Default value:;To;;[I":CSV::DEFAULT_OPTIONS.fetch(:force_quotes) # => false ;T;0o; ;[I""For examples in this section:;To;;[I"ary = ['foo', 0, nil] ;T;0o; ;[I" Using the default, +false+:;To;;[I""str = CSV.generate_line(ary) ;TI"str # => "foo,0,\n" ;T;0o; ;[I"Using +true+:;To;;[I"6str = CSV.generate_line(ary, force_quotes: true) ;TI"%str # => "\"foo\",\"0\",\"\"\n" ;T;0S; ; i;I"Option +quote_empty+;T@o; ;[I"YSpecifies the boolean that determines whether an empty value is to be double-quoted.;T@o; ;[I"Default value:;To;;[I"8CSV::DEFAULT_OPTIONS.fetch(:quote_empty) # => true ;T;0o; ;[I"With the default +true+:;To;;[I"9CSV.generate_line(['"', ""]) # => "\"\"\"\",\"\"\n" ;T;0o; ;[I"With +false+:;To;;[I"ICSV.generate_line(['"', ""], quote_empty: false) # => "\"\"\"\",\n" ;T;0S; ; i;I"Option +write_converters+;T@o; ;[I";Specifies converters to be used in generating fields. ;TI">See {Write Converters}[#class-CSV-label-Write+Converters];T@o; ;[I"Default value:;To;;[I"<CSV::DEFAULT_OPTIONS.fetch(:write_converters) # => nil ;T;0o; ;[I"With no write converter:;To;;[I"8str = CSV.generate_line(["\na\n", "\tb\t", " c "]) ;TI"&str # => "\"\na\n\",\tb\t, c \n" ;T;0o; ;[I"With a write converter:;To;;[I"3strip_converter = proc {|field| field.strip } ;TI"[str = CSV.generate_line(["\na\n", "\tb\t", " c "], write_converters: strip_converter) ;TI"str # => "a,b,c\n" ;T;0o; ;[I"1With two write converters (called in order):;To;;[ I"5upcase_converter = proc {|field| field.upcase } ;TI"9downcase_converter = proc {|field| field.downcase } ;TI"?write_converters = [upcase_converter, downcase_converter] ;TI"Rstr = CSV.generate_line(['a', 'b', 'c'], write_converters: write_converters) ;TI"str # => "a,b,c\n" ;T;0o; ;[I"CSee also {Write Converters}[#class-CSV-label-Write+Converters];T@S; ; i;I"Option +write_nil_value+;T@o; ;[I"PSpecifies the object that is to be substituted for each +nil+-valued field.;T@o; ;[I"Default value:;To;;[I";CSV::DEFAULT_OPTIONS.fetch(:write_nil_value) # => nil ;T;0o; ;[I"Without the option:;To;;[I"3str = CSV.generate_line(['a', nil, 'c', nil]) ;TI"str # => "a,,c,\n" ;T;0o; ;[I"With the option:;To;;[I"Istr = CSV.generate_line(['a', nil, 'c', nil], write_nil_value: "x") ;TI"str # => "a,x,c,x\n" ;T;0S; ; i;I"Option +write_empty_value+;T@o; ;[I"CSpecifies the object that is to be substituted for each field ;TI"that has an empty \String.;T@o; ;[I"Default value:;To;;[I"<CSV::DEFAULT_OPTIONS.fetch(:write_empty_value) # => "" ;T;0o; ;[I"Without the option:;To;;[I"1str = CSV.generate_line(['a', '', 'c', '']) ;TI" str # => "a,\"\",c,\"\"\n" ;T;0o; ;[I"With the option:;To;;[I"Istr = CSV.generate_line(['a', '', 'c', ''], write_empty_value: "x") ;TI"str # => "a,x,c,x\n" ;T;0S; ; i;I"\CSV with Headers;T@o; ;[I"RCSV allows to specify column names of CSV file, whether they are in data, or ;TI"Wprovided separately. If headers are specified, reading methods return an instance ;TI"+of CSV::Table, consisting of CSV::Row.;T@o;;[I" # Headers are part of data ;TI".data = CSV.parse(<<~ROWS, headers: true) ;TI" Name,Department,Salary ;TI" Bob,Engineering,1000 ;TI" Jane,Sales,2000 ;TI" John,Management,5000 ;TI" ROWS ;TI" ;TI"$data.class #=> CSV::Table ;TI"]data.first #=> #<CSV::Row "Name":"Bob" "Department":"Engineering" "Salary":"1000"> ;TI"Xdata.first.to_h #=> {"Name"=>"Bob", "Department"=>"Engineering", "Salary"=>"1000"} ;TI" ;TI"%# Headers provided by developer ;TI"Sdata = CSV.parse('Bob,Engineering,1000', headers: %i[name department salary]) ;TI"Wdata.first #=> #<CSV::Row name:"Bob" department:"Engineering" salary:"1000"> ;T;0S; ; i;I"\Converters;T@o; ;[I"WBy default, each value (field or header) parsed by \CSV is formed into a \String. ;TI"@You can use a _field_ _converter_ or _header_ _converter_ ;TI"/to intercept and modify the parsed values:;To;;;;[o;;0;[o; ;[I"?See {Field Converters}[#class-CSV-label-Field+Converters].;To;;0;[o; ;[I"ASee {Header Converters}[#class-CSV-label-Header+Converters].;T@o; ;[I"UAlso by default, each value to be written during generation is written 'as-is'. ;TI"GYou can use a _write_ _converter_ to modify values before writing.;To;;;;[o;;0;[o; ;[I"?See {Write Converters}[#class-CSV-label-Write+Converters].;T@S; ; i ;I"Specifying \Converters;T@o; ;[I"KYou can specify converters for parsing or generating in the +options+ ;TI"&argument to various \CSV methods:;To;;;;[o;;0;[o; ;[I"<Option +converters+ for converting parsed field values.;To;;0;[o; ;[I"DOption +header_converters+ for converting parsed header values.;To;;0;[o; ;[I"OOption +write_converters+ for converting values to be written (generated).;T@o; ;[I"5There are three forms for specifying converters:;To;;;;[o;;0;[o; ;[I"AA converter proc: executable code to be used for conversion.;To;;0;[o; ;[I"6A converter name: the name of a stored converter.;To;;0;[o; ;[I"YA converter list: an array of converter procs, converter names, and converter lists.;T@S; ; i ;I"Converter Procs;T@o; ;[I"EThis converter proc, +strip_converter+, accepts a value +field+ ;TI"&and returns <tt>field.strip</tt>:;To;;[I"3strip_converter = proc {|field| field.strip } ;T;0o; ;[I")In this call to <tt>CSV.parse</tt>, ;TI"@the keyword argument <tt>converters: string_converter</tt> ;TI"specifies that:;To;;;;[o;;0;[o; ;[I"D\Proc +string_converter+ is to be called for each parsed field.;To;;0;[o; ;[I"BThe converter's return value is to replace the +field+ value.;To; ;[I" Example:;To;;[I"2string = " foo , 0 \n bar , 1 \n baz , 2 \n" ;TI"<array = CSV.parse(string, converters: strip_converter) ;TI";array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"CA converter proc can receive a second argument, +field_info+, ;TI",that contains details about the field. ;TI"<This modified +strip_converter+ displays its arguments:;To;;[I"3strip_converter = proc do |field, field_info| ;TI" p [field, field_info] ;TI" field.strip ;TI" end ;TI"2string = " foo , 0 \n bar , 1 \n baz , 2 \n" ;TI"<array = CSV.parse(string, converters: strip_converter) ;TI";array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"Output:;To;;[I"E[" foo ", #<struct CSV::FieldInfo index=0, line=1, header=nil>] ;TI"C[" 0 ", #<struct CSV::FieldInfo index=1, line=1, header=nil>] ;TI"E[" bar ", #<struct CSV::FieldInfo index=0, line=2, header=nil>] ;TI"C[" 1 ", #<struct CSV::FieldInfo index=1, line=2, header=nil>] ;TI"E[" baz ", #<struct CSV::FieldInfo index=0, line=3, header=nil>] ;TI"C[" 2 ", #<struct CSV::FieldInfo index=1, line=3, header=nil>] ;T;0o; ;[I"&Each CSV::FieldInfo object shows:;To;;;;[o;;0;[o; ;[I"The 0-based field index.;To;;0;[o; ;[I"The 1-based line index.;To;;0;[o; ;[I"The field header, if any.;T@S; ; i ;I"Stored \Converters;T@o; ;[I"EA converter may be given a name and stored in a structure where ;TI"-the parsing methods can find it by name.;T@o; ;[I"NThe storage structure for field converters is the \Hash CSV::Converters. ;TI"-It has several built-in converter procs:;To;;;;[ o;;0;[o; ;[I"T<tt>:integer</tt>: converts each \String-embedded integer into a true \Integer.;To;;0;[o; ;[I"N<tt>:float</tt>: converts each \String-embedded float into a true \Float.;To;;0;[o; ;[I"K<tt>:date</tt>: converts each \String-embedded date into a true \Date.;To;;0;[o; ;[I"X<tt>:date_time</tt>: converts each \String-embedded date-time into a true \DateTime;To; ;[I". ;TI";This example creates a converter proc, then stores it:;To;;[I"3strip_converter = proc {|field| field.strip } ;TI"/CSV::Converters[:strip] = strip_converter ;T;0o; ;[I"=Then the parsing method call can refer to the converter ;TI""by its name, <tt>:strip</tt>:;To;;[I"2string = " foo , 0 \n bar , 1 \n baz , 2 \n" ;TI"3array = CSV.parse(string, converters: :strip) ;TI";array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I"UThe storage structure for header converters is the \Hash CSV::HeaderConverters, ;TI""which works in the same way. ;TI"*It also has built-in converter procs:;To;;;;[o;;0;[o; ;[I"/<tt>:downcase</tt>: Downcases each header.;To;;0;[o; ;[I"9<tt>:symbol</tt>: Converts each header to a \Symbol.;T@o; ;[I":There is no such storage structure for write headers.;T@o; ;[I"[In order for the parsing methods to access stored converters in non-main-Ractors, the ;TI"5storage structure must be made shareable first. ;TI"DTherefore, <tt>Ractor.make_shareable(CSV::Converters)</tt> and ;TI"^<tt>Ractor.make_shareable(CSV::HeaderConverters)</tt> must be called before the creation ;TI"^of Ractors that use the converters stored in these structures. (Since making the storage ;TI"\structures shareable involves freezing them, any custom converters that are to be used ;TI"must be added first.);T@S; ; i ;I"Converter Lists;T@o; ;[I"JA _converter_ _list_ is an \Array that may include any assortment of:;To;;;;[o;;0;[o; ;[I"Converter procs.;To;;0;[o; ;[I" Names of stored converters.;To;;0;[o; ;[I"Nested converter lists.;T@o; ;[I"Examples:;To;;[ I"-numeric_converters = [:integer, :float] ;TI"+date_converters = [:date, :date_time] ;TI"+[numeric_converters, strip_converter] ;TI"0[strip_converter, date_converters, :float] ;T;0o; ;[I"OLike a converter proc, a converter list may be named and stored in either ;TI"/\CSV::Converters or CSV::HeaderConverters:;To;;[I"KCSV::Converters[:custom] = [strip_converter, date_converters, :float] ;TI";CSV::HeaderConverters[:custom] = [:downcase, :symbol] ;T;0o; ;[I",There are two built-in converter lists:;To;;[I"7CSV::Converters[:numeric] # => [:integer, :float] ;TI"7CSV::Converters[:all] # => [:date_time, :numeric] ;T;0S; ; i ;I"Field \Converters;T@o; ;[I"FWith no conversion, all parsed fields in all rows become Strings:;To;;[I"&string = "foo,0\nbar,1\nbaz,2\n" ;TI"ary = CSV.parse(string) ;TI">ary # => # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[ I"WWhen you specify a field converter, each parsed field is passed to the converter; ;TI">its return value becomes the stored value for the field. ;TI"NA converter might, for example, convert an integer embedded in a \String ;TI"into a true \Integer. ;TI"E(In fact, that's what built-in field converter +:integer+ does.);T@o; ;[I"3There are three ways to use field \converters.;T@o;;;;[o;;0;[o; ;[I"YUsing option {converters}[#class-CSV-label-Option+converters] with a parsing method:;To;;[I"3ary = CSV.parse(string, converters: :integer) ;TI"Bary # => [0, 1, 2] # => [["foo", 0], ["bar", 1], ["baz", 2]] ;T;0o;;0;[o; ;[I"\Using option {converters}[#class-CSV-label-Option+converters] with a new \CSV instance:;To;;[ I"1csv = CSV.new(string, converters: :integer) ;TI"## Field converters in effect: ;TI"$csv.converters # => [:integer] ;TI"8csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]] ;T;0o;;0;[o; ;[I"GUsing method #convert to add a field converter to a \CSV instance:;To;;[ I"csv = CSV.new(string) ;TI"# Add a converter. ;TI"csv.convert(:integer) ;TI"$csv.converters # => [:integer] ;TI"8csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]] ;T;0o; ;[I"DInstalling a field converter does not affect already-read rows:;To;;[I"csv = CSV.new(string) ;TI"!csv.shift # => ["foo", "0"] ;TI"# Add a converter. ;TI"csv.convert(:integer) ;TI"$csv.converters # => [:integer] ;TI",csv.read # => [["bar", 1], ["baz", 2]] ;T;0o; ;[I"ZThere are additional built-in \converters, and custom \converters are also supported.;T@S; ; i ;I"Built-In Field \Converters;T@o; ;[I"@The built-in field converters are in \Hash CSV::Converters:;To;;;;[o;;0;[o; ;[I"(Each key is a field converter name.;To;;0;[o; ;[I"Each value is one of:;To;;;;[o;;0;[o; ;[I"A \Proc field converter.;To;;0;[o; ;[I"(An \Array of field converter names.;T@o; ;[I" Display:;To;;[I"0CSV::Converters.each_pair do |name, value| ;TI" if value.kind_of?(Proc) ;TI" p [name, value.class] ;TI" else ;TI" p [name, value] ;TI" end ;TI" end ;T;0o; ;[I"Output:;To;;[I"[:integer, Proc] ;TI"[:float, Proc] ;TI"$[:numeric, [:integer, :float]] ;TI"[:date, Proc] ;TI"[:date_time, Proc] ;TI"$[:all, [:date_time, :numeric]] ;T;0o; ;[I"WEach of these converters transcodes values to UTF-8 before attempting conversion. ;TI"BIf a value cannot be transcoded to UTF-8 the conversion will ;TI"0fail and the value will remain unconverted.;T@o; ;[I"EConverter +:integer+ converts each field that Integer() accepts:;To;;[I"data = '0,1,2,x' ;TI"# Without the converter ;TI" csv = CSV.parse_line(data) ;TI"#csv # => ["0", "1", "2", "x"] ;TI"# With the converter ;TI"6csv = CSV.parse_line(data, converters: :integer) ;TI"csv # => [0, 1, 2, "x"] ;T;0o; ;[I"AConverter +:float+ converts each field that Float() accepts:;To;;[I"data = '1.0,3.14159,x' ;TI"# Without the converter ;TI" csv = CSV.parse_line(data) ;TI"&csv # => ["1.0", "3.14159", "x"] ;TI"# With the converter ;TI"4csv = CSV.parse_line(data, converters: :float) ;TI""csv # => [1.0, 3.14159, "x"] ;T;0o; ;[I"FConverter +:numeric+ converts with both +:integer+ and +:float+..;T@o; ;[I"DConverter +:date+ converts each field that Date::parse accepts:;To;;[I"data = '2001-02-03,x' ;TI"# Without the converter ;TI" csv = CSV.parse_line(data) ;TI""csv # => ["2001-02-03", "x"] ;TI"# With the converter ;TI"3csv = CSV.parse_line(data, converters: :date) ;TI"Icsv # => [#<Date: 2001-02-03 ((2451944j,0s,0n),+0s,2299161j)>, "x"] ;T;0o; ;[I"MConverter +:date_time+ converts each field that DateTime::parse accepts:;To;;[I"*data = '2020-05-07T14:59:00-05:00,x' ;TI"# Without the converter ;TI" csv = CSV.parse_line(data) ;TI"1csv # => ["2020-05-07T14:59:00-05:00", "x"] ;TI"# With the converter ;TI"8csv = CSV.parse_line(data, converters: :date_time) ;TI"dcsv # => [#<DateTime: 2020-05-07T14:59:00-05:00 ((2458977j,71940s,0n),-18000s,2299161j)>, "x"] ;T;0o; ;[I"JConverter +:numeric+ converts with both +:date_time+ and +:numeric+..;T@o; ;[I"IAs seen above, method #convert adds \converters to a \CSV instance, ;TI"Kand method #converters returns an \Array of the \converters in effect:;To;;[I"csv = CSV.new('0,1,2') ;TI"csv.converters # => [] ;TI"csv.convert(:integer) ;TI"$csv.converters # => [:integer] ;TI"csv.convert(:date) ;TI"+csv.converters # => [:integer, :date] ;T;0S; ; i ;I"Custom Field \Converters;T@o; ;[I"-You can define a custom field converter:;To;;[ I"3strip_converter = proc {|field| field.strip } ;TI"2string = " foo , 0 \n bar , 1 \n baz , 2 \n" ;TI"<array = CSV.parse(string, converters: strip_converter) ;TI";array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0o; ;[I":You can register the converter in \Converters \Hash, ;TI"-which allows you to refer to it by name:;To;;[ I"/CSV::Converters[:strip] = strip_converter ;TI"2string = " foo , 0 \n bar , 1 \n baz , 2 \n" ;TI"3array = CSV.parse(string, converters: :strip) ;TI";array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] ;T;0S; ; i ;I"Header \Converters;T@o; ;[I"GHeader converters operate only on headers (and not on other rows).;T@o; ;[I"5There are three ways to use header \converters; ;TI"?these examples use built-in header converter +:downcase+, ;TI"(which downcases each parsed header.;T@o;;;;[o;;0;[o; ;[I"@Option +header_converters+ with a singleton parsing method:;To;;[ I"1string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2" ;TI"Jtbl = CSV.parse(string, headers: true, header_converters: :downcase) ;TI"tbl.class # => CSV::Table ;TI"(tbl.headers # => ["name", "count"] ;T;0o;;0;[o; ;[I"9Option +header_converters+ with a new \CSV instance:;To;;[ I"9csv = CSV.new(string, header_converters: :downcase) ;TI"$# Header converters in effect: ;TI",csv.header_converters # => [:downcase] ;TI",tbl = CSV.parse(string, headers: true) ;TI"(tbl.headers # => ["Name", "Count"] ;T;0o;;0;[o; ;[I"GMethod #header_convert adds a header converter to a \CSV instance:;To;;[I"csv = CSV.new(string) ;TI"# Add a header converter. ;TI"#csv.header_convert(:downcase) ;TI",csv.header_converters # => [:downcase] ;TI",tbl = CSV.parse(string, headers: true) ;TI"(tbl.headers # => ["Name", "Count"] ;T;0S; ; i ;I" Built-In Header \Converters;T@o; ;[I"IThe built-in header \converters are in \Hash CSV::HeaderConverters. ;TI"5The keys there are the names of the \converters:;To;;[I":CSV::HeaderConverters.keys # => [:downcase, :symbol] ;T;0o; ;[I"AConverter +:downcase+ converts each header by downcasing it:;To;;[ I"1string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2" ;TI"Jtbl = CSV.parse(string, headers: true, header_converters: :downcase) ;TI"tbl.class # => CSV::Table ;TI"(tbl.headers # => ["name", "count"] ;T;0o; ;[I"JConverter +:symbol+ converts each header by making it into a \Symbol:;To;;[I"1string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2" ;TI"Htbl = CSV.parse(string, headers: true, header_converters: :symbol) ;TI"&tbl.headers # => [:name, :count] ;T;0o; ;[I" Details:;To;;;;[ o;;0;[o; ;[I",Strips leading and trailing whitespace.;To;;0;[o; ;[I"Downcases the header.;To;;0;[o; ;[I"/Replaces embedded spaces with underscores.;To;;0;[o; ;[I"!Removes non-word characters.;To;;0;[o; ;[I"%Makes the string into a \Symbol.;T@S; ; i ;I"Custom Header \Converters;T@o; ;[I".You can define a custom header converter:;To;;[ I"7upcase_converter = proc {|header| header.upcase } ;TI"2string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" ;TI"Stable = CSV.parse(string, headers: true, header_converters: upcase_converter) ;TI":table # => #<CSV::Table mode:col_or_row row_count:4> ;TI"*table.headers # => ["NAME", "VALUE"] ;T;0o; ;[I"@You can register the converter in \HeaderConverters \Hash, ;TI"-which allows you to refer to it by name:;To;;[ I"7CSV::HeaderConverters[:upcase] = upcase_converter ;TI"Jtable = CSV.parse(string, headers: true, header_converters: :upcase) ;TI":table # => #<CSV::Table mode:col_or_row row_count:4> ;TI"*table.headers # => ["NAME", "VALUE"] ;T;0S; ; i ;I"Write \Converters;T@o; ;[ I"=When you specify a write converter for generating \CSV, ;TI":each field to be written is passed to the converter; ;TI";its return value becomes the new value for the field. ;TI"CA converter might, for example, strip whitespace from a field.;T@o; ;[I"6Using no write converter (all fields unmodified):;To;;[I"+output_string = CSV.generate do |csv| ;TI" csv << [' foo ', 0] ;TI" csv << [' bar ', 1] ;TI" csv << [' baz ', 2] ;TI" end ;TI"6output_string # => " foo ,0\n bar ,1\n baz ,2\n" ;T;0o; ;[I"FUsing option +write_converters+ with two custom write converters:;To;;[I"Wstrip_converter = proc {|field| field.respond_to?(:strip) ? field.strip : field } ;TI"Zupcase_converter = proc {|field| field.respond_to?(:upcase) ? field.upcase : field } ;TI"<write_converters = [strip_converter, upcase_converter] ;TI"Ooutput_string = CSV.generate(write_converters: write_converters) do |csv| ;TI" csv << [' foo ', 0] ;TI" csv << [' bar ', 1] ;TI" csv << [' baz ', 2] ;TI" end ;TI"0output_string # => "FOO,0\nBAR,1\nBAZ,2\n" ;T;0S; ; i;I"6Character Encodings (M17n or Multilingualization);T@o; ;[I"TThis new CSV parser is m17n savvy. The parser works in the Encoding of the IO ;TI"Sor String object being read from or written to. Your data is never transcoded ;TI"S(unless you ask Ruby to transcode it for you) and will literally be parsed in ;TI"Rthe Encoding it is in. Thus CSV will return Arrays or Rows of Strings in the ;TI"REncoding of your data. This is accomplished by transcoding the parser itself ;TI"into your Encoding.;T@o; ;[I"SSome transcoding must take place, of course, to accomplish this multiencoding ;TI"Esupport. For example, <tt>:col_sep</tt>, <tt>:row_sep</tt>, and ;TI"Q<tt>:quote_char</tt> must be transcoded to match your data. Hopefully this ;TI"Qmakes the entire process feel transparent, since CSV's defaults should just ;TI"Qmagically work for your data. However, you can set these values manually in ;TI"2the target Encoding to avoid the translation.;T@o; ;[I"LIt's also important to note that while all of CSV's core parser is now ;TI"IEncoding agnostic, some features are not. For example, the built-in ;TI"Oconverters will try to transcode data to UTF-8 before making conversions. ;TI"RAgain, you can provide custom converters that are aware of your Encodings to ;TI"Iavoid this translation. It's just too hard for me to support native ;TI",conversions in all of Ruby's Encodings.;T@o; ;[ I"SAnyway, the practical side of this is simple: make sure IO and String objects ;TI"Spassed into CSV have the proper Encoding set and everything should just work. ;TI"QCSV methods that allow you to open IO objects (CSV::foreach(), CSV::open(), ;TI"MCSV::read(), and CSV::readlines()) do allow you to specify the Encoding.;T@o; ;[ I"ROne minor exception comes when generating CSV into a String with an Encoding ;TI"Nthat is not ASCII compatible. There's no existing data for CSV to use to ;TI"Tprepare itself and thus you will probably need to manually specify the desired ;TI"REncoding for most of those cases. It will try to guess using the fields in a ;TI"Mrow of output though, when using CSV::generate_line() or Array#to_csv().;T@o; ;[I"RI try to point out any other Encoding issues in the documentation of methods ;TI"as they come up.;T@o; ;[ I"SThis has been tested to the best of my ability with all non-"dummy" Encodings ;TI"LRuby ships with. However, it is brave new code and may have some bugs. ;TI"SPlease feel free to {report}[mailto:james@grayproductions.net] any issues you ;TI"find with it.;T: @fileI"lib/csv.rb;T:0@omit_headings_from_table_of_contents_below0o;;[ ;I" lib/csv/fields_converter.rb;T;0o;;[ ;I"&lib/csv/input_record_separator.rb;T;0o;;[ ;I"lib/csv/parser.rb;T;0o;;[ ;I"lib/csv/row.rb;T;0o;;[ ;I"lib/csv/table.rb;T;0o;;[ ;I"lib/csv/version.rb;T;0o;;[ ;I"lib/csv/writer.rb;T;0;0;0[[ I" encoding;TI"R;T:privateFI"lib/csv.rb;T[ U:RDoc::Constant[i I"FieldInfo;TI"CSV::FieldInfo;T:public0o;;[o; ;[ I"NA FieldInfo Struct contains details about a field's position in the data ;TI"Rsource it was read from. CSV will pass this Struct to some blocks that make ;TI"Jdecisions based on field structure. See CSV.convert_fields() for an ;TI" example.;T@o;;: NOTE;[ o;;[I"<b><tt>index</tt></b>;T;[o; ;[I"2The zero-based index of the field in its row.;To;;[I"<b><tt>line</tt></b>;T;[o; ;[I"2The line of the data source this row is from.;To;;[I"<b><tt>header</tt></b>;T;[o; ;[I"/The header for the column, when available.;To;;[I"<b><tt>quoted?</tt></b>;T;[o; ;[I"@True or false, whether the original value is quoted or not.;T;@� ;0@� @cRDoc::NormalClass0U;[i I"DateMatcher;TI"CSV::DateMatcher;T;0o;;[o; ;[I"@A Regexp used to find and convert some common Date formats.;T;@� ;0@� @@� 0U;[i I"DateTimeMatcher;TI"CSV::DateTimeMatcher;T;0o;;[o; ;[I"DA Regexp used to find and convert some common DateTime formats.;T;@� ;0@� @@� 0U;[i I"ConverterEncoding;TI"CSV::ConverterEncoding;T;0o;;[o; ;[I")The encoding used by all converters.;T;@� ;0@� @@� 0U;[i I"Converters;TI"CSV::Converters;T;0o;;[o; ;[I"PA \Hash containing the names and \Procs for the built-in field converters. ;TI"QSee {Built-In Field Converters}[#class-CSV-label-Built-In+Field+Converters].;T@o; ;[I"IThis \Hash is intentionally left unfrozen, and may be extended with ;TI"custom field converters. ;TI"MSee {Custom Field Converters}[#class-CSV-label-Custom+Field+Converters].;T;@� ;0@� @@� 0U;[i I"HeaderConverters;TI"CSV::HeaderConverters;T;0o;;[o; ;[I"QA \Hash containing the names and \Procs for the built-in header converters. ;TI"SSee {Built-In Header Converters}[#class-CSV-label-Built-In+Header+Converters].;T@o; ;[I"IThis \Hash is intentionally left unfrozen, and may be extended with ;TI"custom field converters. ;TI"OSee {Custom Header Converters}[#class-CSV-label-Custom+Header+Converters].;T;@� ;0@� @@� 0U;[i I"DEFAULT_OPTIONS;TI"CSV::DEFAULT_OPTIONS;T;0o;;[o; ;[I"'Default values for method options.;T;@� ;0@� @@� 0U;[i I"VERSION;TI"CSV::VERSION;T;0o;;[o; ;[I"*The version of the installed library.;T;@� ;0@� @@� 0[[I"Enumerable;To;;[ ;@� ;0@� [[I" class;T[[;[ [:protected[ [;[[I"filter;T@� [I"foreach;T@� [I" generate;T@� [I"generate_line;T@� [I"generate_lines;T@� [I" instance;T@� [I"new;T@� [I" open;T@� [I" parse;T@� [I"parse_line;T@� [I" read;T@� [I"readlines;T@� [I" table;T@� [I" instance;T[[;[ [;[ [;[=[I"<<;T@� [I"add_row;T@� [I" binmode?;T@� [I"build_fields_converter;T@� [I""build_header_fields_converter;T@� [I""build_parser_fields_converter;T@� [I""build_writer_fields_converter;T@� [I"col_sep;T@� [I"convert;T@� [I"convert_fields;T@� [I"converters;T@� [I"determine_encoding;T@� [I" each;T@� [I"eof;T@� [I" eof?;T@� [I"field_size_limit;T@� [I" flock;T@� [I"force_quotes?;T@� [I" gets;T@� [I"header_convert;T@� [I"header_converters;T@� [I"header_fields_converter;T@� [I"header_row?;T@� [I"headers;T@� [I"inspect;T@� [I" ioctl;T@� [I"liberal_parsing?;T@� [I" line;T@� [I"lineno;T@� [I"max_field_size;T@� [I"normalize_converters;T@� [I"parser;T@� [I"parser_enumerator;T@� [I"parser_fields_converter;T@� [I"parser_options;T@� [I" path;T@� [I" puts;T@� [I"quote_char;T@� [I"raw_encoding;T@� [I" read;T@� [I" readline;T@� [I"readlines;T@� [I"return_headers?;T@� [I"rewind;T@� [I"row_sep;T@� [I" shift;T@� [I"skip_blanks?;T@� [I"skip_lines;T@� [I" stat;T@� [I" to_i;T@� [I" to_io;T@� [I"unconverted_fields?;T@� [I"write_headers?;T@� [I"writer;T@� [I"writer_fields_converter;T@� [I"writer_options;T@� [[I"Forwardable;To;;[o; ;[I"#IO and StringIO Delegation ###;T;@� ;0@� [U:RDoc::Context::Section[i 0o;;[ ;0;0[ I"lib/csv.rb;TI" lib/csv/fields_converter.rb;TI"&lib/csv/input_record_separator.rb;TI"lib/csv/parser.rb;TI"lib/csv/row.rb;TI"lib/csv/table.rb;TI"lib/csv/version.rb;TI"lib/csv/writer.rb;T@� cRDoc::TopLevel