csv 1.0.2 → 3.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS.md +868 -0
  3. data/README.md +6 -3
  4. data/doc/csv/arguments/io.rdoc +5 -0
  5. data/doc/csv/options/common/col_sep.rdoc +57 -0
  6. data/doc/csv/options/common/quote_char.rdoc +42 -0
  7. data/doc/csv/options/common/row_sep.rdoc +91 -0
  8. data/doc/csv/options/generating/force_quotes.rdoc +17 -0
  9. data/doc/csv/options/generating/quote_empty.rdoc +12 -0
  10. data/doc/csv/options/generating/write_converters.rdoc +25 -0
  11. data/doc/csv/options/generating/write_empty_value.rdoc +15 -0
  12. data/doc/csv/options/generating/write_headers.rdoc +29 -0
  13. data/doc/csv/options/generating/write_nil_value.rdoc +14 -0
  14. data/doc/csv/options/parsing/converters.rdoc +46 -0
  15. data/doc/csv/options/parsing/empty_value.rdoc +13 -0
  16. data/doc/csv/options/parsing/field_size_limit.rdoc +39 -0
  17. data/doc/csv/options/parsing/header_converters.rdoc +43 -0
  18. data/doc/csv/options/parsing/headers.rdoc +63 -0
  19. data/doc/csv/options/parsing/liberal_parsing.rdoc +38 -0
  20. data/doc/csv/options/parsing/nil_value.rdoc +12 -0
  21. data/doc/csv/options/parsing/return_headers.rdoc +22 -0
  22. data/doc/csv/options/parsing/skip_blanks.rdoc +31 -0
  23. data/doc/csv/options/parsing/skip_lines.rdoc +37 -0
  24. data/doc/csv/options/parsing/strip.rdoc +15 -0
  25. data/doc/csv/options/parsing/unconverted_fields.rdoc +27 -0
  26. data/doc/csv/recipes/filtering.rdoc +158 -0
  27. data/doc/csv/recipes/generating.rdoc +298 -0
  28. data/doc/csv/recipes/parsing.rdoc +545 -0
  29. data/doc/csv/recipes/recipes.rdoc +6 -0
  30. data/lib/csv/core_ext/array.rb +1 -1
  31. data/lib/csv/core_ext/string.rb +1 -1
  32. data/lib/csv/fields_converter.rb +89 -0
  33. data/lib/csv/input_record_separator.rb +18 -0
  34. data/lib/csv/parser.rb +1290 -0
  35. data/lib/csv/row.rb +505 -136
  36. data/lib/csv/table.rb +791 -114
  37. data/lib/csv/version.rb +1 -1
  38. data/lib/csv/writer.rb +210 -0
  39. data/lib/csv.rb +2432 -1329
  40. metadata +66 -13
  41. data/news.md +0 -112
data/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
  # CSV
2
2
 
3
- [![Build Status](https://travis-ci.org/ruby/csv.svg?branch=master)](https://travis-ci.org/ruby/csv)
4
-
5
3
  This library provides a complete interface to CSV files and data. It offers tools to enable you to read and write to and from Strings or IO objects, as needed.
6
4
 
7
5
  ## Installation
@@ -30,9 +28,14 @@ CSV.foreach("path/to/file.csv") do |row|
30
28
  end
31
29
  ```
32
30
 
31
+ ## Documentation
32
+
33
+ - [API](https://ruby-doc.org/stdlib/libdoc/csv/rdoc/CSV.html): all classes, methods, and constants.
34
+ - [Recipes](https://ruby-doc.org/core/doc/csv/recipes/recipes_rdoc.html): specific code for specific tasks.
35
+
33
36
  ## Development
34
37
 
35
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
38
+ After checking out the repo, run `ruby run-test.rb` to check if your changes can pass the test.
36
39
 
37
40
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
38
41
 
@@ -0,0 +1,5 @@
1
+ * Argument +io+ should be an IO object that is:
2
+ * Open for reading; on return, the IO object will be closed.
3
+ * Positioned at the beginning.
4
+ To position at the end, for appending, use method CSV.generate.
5
+ For any other positioning, pass a preset \StringIO object instead.
@@ -0,0 +1,57 @@
1
+ ====== Option +col_sep+
2
+
3
+ Specifies the \String column separator to be used
4
+ for both parsing and generating.
5
+ The \String will be transcoded into the data's \Encoding before use.
6
+
7
+ Default value:
8
+ CSV::DEFAULT_OPTIONS.fetch(:col_sep) # => "," (comma)
9
+
10
+ Using the default (comma):
11
+ str = CSV.generate do |csv|
12
+ csv << [:foo, 0]
13
+ csv << [:bar, 1]
14
+ csv << [:baz, 2]
15
+ end
16
+ str # => "foo,0\nbar,1\nbaz,2\n"
17
+ ary = CSV.parse(str)
18
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
19
+
20
+ Using +:+ (colon):
21
+ col_sep = ':'
22
+ str = CSV.generate(col_sep: col_sep) do |csv|
23
+ csv << [:foo, 0]
24
+ csv << [:bar, 1]
25
+ csv << [:baz, 2]
26
+ end
27
+ str # => "foo:0\nbar:1\nbaz:2\n"
28
+ ary = CSV.parse(str, col_sep: col_sep)
29
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
30
+
31
+ Using +::+ (two colons):
32
+ col_sep = '::'
33
+ str = CSV.generate(col_sep: col_sep) do |csv|
34
+ csv << [:foo, 0]
35
+ csv << [:bar, 1]
36
+ csv << [:baz, 2]
37
+ end
38
+ str # => "foo::0\nbar::1\nbaz::2\n"
39
+ ary = CSV.parse(str, col_sep: col_sep)
40
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
41
+
42
+ Using <tt>''</tt> (empty string):
43
+ col_sep = ''
44
+ str = CSV.generate(col_sep: col_sep) do |csv|
45
+ csv << [:foo, 0]
46
+ csv << [:bar, 1]
47
+ csv << [:baz, 2]
48
+ end
49
+ str # => "foo0\nbar1\nbaz2\n"
50
+
51
+ ---
52
+
53
+ Raises an exception if parsing with the empty \String:
54
+ col_sep = ''
55
+ # Raises ArgumentError (:col_sep must be 1 or more characters: "")
56
+ CSV.parse("foo0\nbar1\nbaz2\n", col_sep: col_sep)
57
+
@@ -0,0 +1,42 @@
1
+ ====== Option +quote_char+
2
+
3
+ Specifies the character (\String of length 1) used used to quote fields
4
+ in both parsing and generating.
5
+ This String will be transcoded into the data's \Encoding before use.
6
+
7
+ Default value:
8
+ CSV::DEFAULT_OPTIONS.fetch(:quote_char) # => "\"" (double quote)
9
+
10
+ This is useful for an application that incorrectly uses <tt>'</tt> (single-quote)
11
+ to quote fields, instead of the correct <tt>"</tt> (double-quote).
12
+
13
+ Using the default (double quote):
14
+ str = CSV.generate do |csv|
15
+ csv << ['foo', 0]
16
+ csv << ["'bar'", 1]
17
+ csv << ['"baz"', 2]
18
+ end
19
+ str # => "foo,0\n'bar',1\n\"\"\"baz\"\"\",2\n"
20
+ ary = CSV.parse(str)
21
+ ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]]
22
+
23
+ Using <tt>'</tt> (single-quote):
24
+ quote_char = "'"
25
+ str = CSV.generate(quote_char: quote_char) do |csv|
26
+ csv << ['foo', 0]
27
+ csv << ["'bar'", 1]
28
+ csv << ['"baz"', 2]
29
+ end
30
+ str # => "foo,0\n'''bar''',1\n\"baz\",2\n"
31
+ ary = CSV.parse(str, quote_char: quote_char)
32
+ ary # => [["foo", "0"], ["'bar'", "1"], ["\"baz\"", "2"]]
33
+
34
+ ---
35
+
36
+ Raises an exception if the \String length is greater than 1:
37
+ # Raises ArgumentError (:quote_char has to be nil or a single character String)
38
+ CSV.new('', quote_char: 'xx')
39
+
40
+ Raises an exception if the value is not a \String:
41
+ # Raises ArgumentError (:quote_char has to be nil or a single character String)
42
+ CSV.new('', quote_char: :foo)
@@ -0,0 +1,91 @@
1
+ ====== Option +row_sep+
2
+
3
+ Specifies the row separator, a \String or the \Symbol <tt>:auto</tt> (see below),
4
+ to be used for both parsing and generating.
5
+
6
+ Default value:
7
+ CSV::DEFAULT_OPTIONS.fetch(:row_sep) # => :auto
8
+
9
+ ---
10
+
11
+ When +row_sep+ is a \String, that \String becomes the row separator.
12
+ The String will be transcoded into the data's Encoding before use.
13
+
14
+ Using <tt>"\n"</tt>:
15
+ row_sep = "\n"
16
+ str = CSV.generate(row_sep: row_sep) do |csv|
17
+ csv << [:foo, 0]
18
+ csv << [:bar, 1]
19
+ csv << [:baz, 2]
20
+ end
21
+ str # => "foo,0\nbar,1\nbaz,2\n"
22
+ ary = CSV.parse(str)
23
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
24
+
25
+ Using <tt>|</tt> (pipe):
26
+ row_sep = '|'
27
+ str = CSV.generate(row_sep: row_sep) do |csv|
28
+ csv << [:foo, 0]
29
+ csv << [:bar, 1]
30
+ csv << [:baz, 2]
31
+ end
32
+ str # => "foo,0|bar,1|baz,2|"
33
+ ary = CSV.parse(str, row_sep: row_sep)
34
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
35
+
36
+ Using <tt>--</tt> (two hyphens):
37
+ row_sep = '--'
38
+ str = CSV.generate(row_sep: row_sep) do |csv|
39
+ csv << [:foo, 0]
40
+ csv << [:bar, 1]
41
+ csv << [:baz, 2]
42
+ end
43
+ str # => "foo,0--bar,1--baz,2--"
44
+ ary = CSV.parse(str, row_sep: row_sep)
45
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
46
+
47
+ Using <tt>''</tt> (empty string):
48
+ row_sep = ''
49
+ str = CSV.generate(row_sep: row_sep) do |csv|
50
+ csv << [:foo, 0]
51
+ csv << [:bar, 1]
52
+ csv << [:baz, 2]
53
+ end
54
+ str # => "foo,0bar,1baz,2"
55
+ ary = CSV.parse(str, row_sep: row_sep)
56
+ ary # => [["foo", "0bar", "1baz", "2"]]
57
+
58
+ ---
59
+
60
+ When +row_sep+ is the \Symbol +:auto+ (the default),
61
+ generating uses <tt>"\n"</tt> as the row separator:
62
+ str = CSV.generate do |csv|
63
+ csv << [:foo, 0]
64
+ csv << [:bar, 1]
65
+ csv << [:baz, 2]
66
+ end
67
+ str # => "foo,0\nbar,1\nbaz,2\n"
68
+
69
+ Parsing, on the other hand, invokes auto-discovery of the row separator.
70
+
71
+ Auto-discovery reads ahead in the data looking for the next <tt>\r\n</tt>, +\n+, or +\r+ sequence.
72
+ The sequence will be selected even if it occurs in a quoted field,
73
+ assuming that you would have the same line endings there.
74
+
75
+ Example:
76
+ str = CSV.generate do |csv|
77
+ csv << [:foo, 0]
78
+ csv << [:bar, 1]
79
+ csv << [:baz, 2]
80
+ end
81
+ str # => "foo,0\nbar,1\nbaz,2\n"
82
+ ary = CSV.parse(str)
83
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
84
+
85
+ The default <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>) is used
86
+ if any of the following is true:
87
+ * None of those sequences is found.
88
+ * Data is +ARGF+, +STDIN+, +STDOUT+, or +STDERR+.
89
+ * The stream is only available for output.
90
+
91
+ 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.
@@ -0,0 +1,17 @@
1
+ ====== Option +force_quotes+
2
+
3
+ Specifies the boolean that determines whether each output field is to be double-quoted.
4
+
5
+ Default value:
6
+ CSV::DEFAULT_OPTIONS.fetch(:force_quotes) # => false
7
+
8
+ For examples in this section:
9
+ ary = ['foo', 0, nil]
10
+
11
+ Using the default, +false+:
12
+ str = CSV.generate_line(ary)
13
+ str # => "foo,0,\n"
14
+
15
+ Using +true+:
16
+ str = CSV.generate_line(ary, force_quotes: true)
17
+ str # => "\"foo\",\"0\",\"\"\n"
@@ -0,0 +1,12 @@
1
+ ====== Option +quote_empty+
2
+
3
+ Specifies the boolean that determines whether an empty value is to be double-quoted.
4
+
5
+ Default value:
6
+ CSV::DEFAULT_OPTIONS.fetch(:quote_empty) # => true
7
+
8
+ With the default +true+:
9
+ CSV.generate_line(['"', ""]) # => "\"\"\"\",\"\"\n"
10
+
11
+ With +false+:
12
+ CSV.generate_line(['"', ""], quote_empty: false) # => "\"\"\"\",\n"
@@ -0,0 +1,25 @@
1
+ ====== Option +write_converters+
2
+
3
+ Specifies converters to be used in generating fields.
4
+ See {Write Converters}[#class-CSV-label-Write+Converters]
5
+
6
+ Default value:
7
+ CSV::DEFAULT_OPTIONS.fetch(:write_converters) # => nil
8
+
9
+ With no write converter:
10
+ str = CSV.generate_line(["\na\n", "\tb\t", " c "])
11
+ str # => "\"\na\n\",\tb\t, c \n"
12
+
13
+ With a write converter:
14
+ strip_converter = proc {|field| field.strip }
15
+ str = CSV.generate_line(["\na\n", "\tb\t", " c "], write_converters: strip_converter)
16
+ str # => "a,b,c\n"
17
+
18
+ With two write converters (called in order):
19
+ upcase_converter = proc {|field| field.upcase }
20
+ downcase_converter = proc {|field| field.downcase }
21
+ write_converters = [upcase_converter, downcase_converter]
22
+ str = CSV.generate_line(['a', 'b', 'c'], write_converters: write_converters)
23
+ str # => "a,b,c\n"
24
+
25
+ See also {Write Converters}[#class-CSV-label-Write+Converters]
@@ -0,0 +1,15 @@
1
+ ====== Option +write_empty_value+
2
+
3
+ Specifies the object that is to be substituted for each field
4
+ that has an empty \String.
5
+
6
+ Default value:
7
+ CSV::DEFAULT_OPTIONS.fetch(:write_empty_value) # => ""
8
+
9
+ Without the option:
10
+ str = CSV.generate_line(['a', '', 'c', ''])
11
+ str # => "a,\"\",c,\"\"\n"
12
+
13
+ With the option:
14
+ str = CSV.generate_line(['a', '', 'c', ''], write_empty_value: "x")
15
+ str # => "a,x,c,x\n"
@@ -0,0 +1,29 @@
1
+ ====== Option +write_headers+
2
+
3
+ Specifies the boolean that determines whether a header row is included in the output;
4
+ ignored if there are no headers.
5
+
6
+ Default value:
7
+ CSV::DEFAULT_OPTIONS.fetch(:write_headers) # => nil
8
+
9
+ Without +write_headers+:
10
+ file_path = 't.csv'
11
+ CSV.open(file_path,'w',
12
+ :headers => ['Name','Value']
13
+ ) do |csv|
14
+ csv << ['foo', '0']
15
+ end
16
+ CSV.open(file_path) do |csv|
17
+ csv.shift
18
+ end # => ["foo", "0"]
19
+
20
+ With +write_headers+":
21
+ CSV.open(file_path,'w',
22
+ :write_headers => true,
23
+ :headers => ['Name','Value']
24
+ ) do |csv|
25
+ csv << ['foo', '0']
26
+ end
27
+ CSV.open(file_path) do |csv|
28
+ csv.shift
29
+ end # => ["Name", "Value"]
@@ -0,0 +1,14 @@
1
+ ====== Option +write_nil_value+
2
+
3
+ Specifies the object that is to be substituted for each +nil+-valued field.
4
+
5
+ Default value:
6
+ CSV::DEFAULT_OPTIONS.fetch(:write_nil_value) # => nil
7
+
8
+ Without the option:
9
+ str = CSV.generate_line(['a', nil, 'c', nil])
10
+ str # => "a,,c,\n"
11
+
12
+ With the option:
13
+ str = CSV.generate_line(['a', nil, 'c', nil], write_nil_value: "x")
14
+ str # => "a,x,c,x\n"
@@ -0,0 +1,46 @@
1
+ ====== Option +converters+
2
+
3
+ Specifies converters to be used in parsing fields.
4
+ See {Field Converters}[#class-CSV-label-Field+Converters]
5
+
6
+ Default value:
7
+ CSV::DEFAULT_OPTIONS.fetch(:converters) # => nil
8
+
9
+ The value may be a field converter name
10
+ (see {Stored Converters}[#class-CSV-label-Stored+Converters]):
11
+ str = '1,2,3'
12
+ # Without a converter
13
+ array = CSV.parse_line(str)
14
+ array # => ["1", "2", "3"]
15
+ # With built-in converter :integer
16
+ array = CSV.parse_line(str, converters: :integer)
17
+ array # => [1, 2, 3]
18
+
19
+ The value may be a converter list
20
+ (see {Converter Lists}[#class-CSV-label-Converter+Lists]):
21
+ str = '1,3.14159'
22
+ # Without converters
23
+ array = CSV.parse_line(str)
24
+ array # => ["1", "3.14159"]
25
+ # With built-in converters
26
+ array = CSV.parse_line(str, converters: [:integer, :float])
27
+ array # => [1, 3.14159]
28
+
29
+ The value may be a \Proc custom converter:
30
+ (see {Custom Field Converters}[#class-CSV-label-Custom+Field+Converters]):
31
+ str = ' foo , bar , baz '
32
+ # Without a converter
33
+ array = CSV.parse_line(str)
34
+ array # => [" foo ", " bar ", " baz "]
35
+ # With a custom converter
36
+ array = CSV.parse_line(str, converters: proc {|field| field.strip })
37
+ array # => ["foo", "bar", "baz"]
38
+
39
+ See also {Custom Field Converters}[#class-CSV-label-Custom+Field+Converters]
40
+
41
+ ---
42
+
43
+ Raises an exception if the converter is not a converter name or a \Proc:
44
+ str = 'foo,0'
45
+ # Raises NoMethodError (undefined method `arity' for nil:NilClass)
46
+ CSV.parse(str, converters: :foo)
@@ -0,0 +1,13 @@
1
+ ====== Option +empty_value+
2
+
3
+ Specifies the object that is to be substituted
4
+ for each field that has an empty \String.
5
+
6
+ Default value:
7
+ CSV::DEFAULT_OPTIONS.fetch(:empty_value) # => "" (empty string)
8
+
9
+ With the default, <tt>""</tt>:
10
+ CSV.parse_line('a,"",b,"",c') # => ["a", "", "b", "", "c"]
11
+
12
+ With a different object:
13
+ CSV.parse_line('a,"",b,"",c', empty_value: 'x') # => ["a", "x", "b", "x", "c"]
@@ -0,0 +1,39 @@
1
+ ====== Option +field_size_limit+
2
+
3
+ Specifies the \Integer field size limit.
4
+
5
+ Default value:
6
+ CSV::DEFAULT_OPTIONS.fetch(:field_size_limit) # => nil
7
+
8
+ This is a maximum size CSV will read ahead looking for the closing quote for a field.
9
+ (In truth, it reads to the first line ending beyond this size.)
10
+ If a quote cannot be found within the limit CSV will raise a MalformedCSVError,
11
+ assuming the data is faulty.
12
+ You can use this limit to prevent what are effectively DoS attacks on the parser.
13
+ However, this limit can cause a legitimate parse to fail;
14
+ therefore the default value is +nil+ (no limit).
15
+
16
+ For the examples in this section:
17
+ str = <<~EOT
18
+ "a","b"
19
+ "
20
+ 2345
21
+ ",""
22
+ EOT
23
+ str # => "\"a\",\"b\"\n\"\n2345\n\",\"\"\n"
24
+
25
+ Using the default +nil+:
26
+ ary = CSV.parse(str)
27
+ ary # => [["a", "b"], ["\n2345\n", ""]]
28
+
29
+ Using <tt>50</tt>:
30
+ field_size_limit = 50
31
+ ary = CSV.parse(str, field_size_limit: field_size_limit)
32
+ ary # => [["a", "b"], ["\n2345\n", ""]]
33
+
34
+ ---
35
+
36
+ Raises an exception if a field is too long:
37
+ big_str = "123456789\n" * 1024
38
+ # Raises CSV::MalformedCSVError (Field size exceeded in line 1.)
39
+ CSV.parse('valid,fields,"' + big_str + '"', field_size_limit: 2048)
@@ -0,0 +1,43 @@
1
+ ====== Option +header_converters+
2
+
3
+ Specifies converters to be used in parsing headers.
4
+ See {Header Converters}[#class-CSV-label-Header+Converters]
5
+
6
+ Default value:
7
+ CSV::DEFAULT_OPTIONS.fetch(:header_converters) # => nil
8
+
9
+ Identical in functionality to option {converters}[#class-CSV-label-Option+converters]
10
+ except that:
11
+ - The converters apply only to the header row.
12
+ - The built-in header converters are +:downcase+ and +:symbol+.
13
+
14
+ This section assumes prior execution of:
15
+ str = <<-EOT
16
+ Name,Value
17
+ foo,0
18
+ bar,1
19
+ baz,2
20
+ EOT
21
+ # With no header converter
22
+ table = CSV.parse(str, headers: true)
23
+ table.headers # => ["Name", "Value"]
24
+
25
+ The value may be a header converter name
26
+ (see {Stored Converters}[#class-CSV-label-Stored+Converters]):
27
+ table = CSV.parse(str, headers: true, header_converters: :downcase)
28
+ table.headers # => ["name", "value"]
29
+
30
+ The value may be a converter list
31
+ (see {Converter Lists}[#class-CSV-label-Converter+Lists]):
32
+ header_converters = [:downcase, :symbol]
33
+ table = CSV.parse(str, headers: true, header_converters: header_converters)
34
+ table.headers # => [:name, :value]
35
+
36
+ The value may be a \Proc custom converter
37
+ (see {Custom Header Converters}[#class-CSV-label-Custom+Header+Converters]):
38
+ upcase_converter = proc {|field| field.upcase }
39
+ table = CSV.parse(str, headers: true, header_converters: upcase_converter)
40
+ table.headers # => ["NAME", "VALUE"]
41
+
42
+ See also {Custom Header Converters}[#class-CSV-label-Custom+Header+Converters]
43
+
@@ -0,0 +1,63 @@
1
+ ====== Option +headers+
2
+
3
+ Specifies a boolean, \Symbol, \Array, or \String to be used
4
+ to define column headers.
5
+
6
+ Default value:
7
+ CSV::DEFAULT_OPTIONS.fetch(:headers) # => false
8
+
9
+ ---
10
+
11
+ Without +headers+:
12
+ str = <<-EOT
13
+ Name,Count
14
+ foo,0
15
+ bar,1
16
+ bax,2
17
+ EOT
18
+ csv = CSV.new(str)
19
+ csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
20
+ csv.headers # => nil
21
+ csv.shift # => ["Name", "Count"]
22
+
23
+ ---
24
+
25
+ If set to +true+ or the \Symbol +:first_row+,
26
+ the first row of the data is treated as a row of headers:
27
+ str = <<-EOT
28
+ Name,Count
29
+ foo,0
30
+ bar,1
31
+ bax,2
32
+ EOT
33
+ csv = CSV.new(str, headers: true)
34
+ csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:2 col_sep:"," row_sep:"\n" quote_char:"\"" headers:["Name", "Count"]>
35
+ csv.headers # => ["Name", "Count"]
36
+ csv.shift # => #<CSV::Row "Name":"bar" "Count":"1">
37
+
38
+ ---
39
+
40
+ If set to an \Array, the \Array elements are treated as headers:
41
+ str = <<-EOT
42
+ foo,0
43
+ bar,1
44
+ bax,2
45
+ EOT
46
+ csv = CSV.new(str, headers: ['Name', 'Count'])
47
+ csv
48
+ csv.headers # => ["Name", "Count"]
49
+ csv.shift # => #<CSV::Row "Name":"bar" "Count":"1">
50
+
51
+ ---
52
+
53
+ If set to a \String +str+, method <tt>CSV::parse_line(str, options)</tt> is called
54
+ with the current +options+, and the returned \Array is treated as headers:
55
+ str = <<-EOT
56
+ foo,0
57
+ bar,1
58
+ bax,2
59
+ EOT
60
+ csv = CSV.new(str, headers: 'Name,Count')
61
+ csv
62
+ csv.headers # => ["Name", "Count"]
63
+ csv.shift # => #<CSV::Row "Name":"bar" "Count":"1">
@@ -0,0 +1,38 @@
1
+ ====== Option +liberal_parsing+
2
+
3
+ Specifies the boolean or hash value that determines whether
4
+ CSV will attempt to parse input not conformant with RFC 4180,
5
+ such as double quotes in unquoted fields.
6
+
7
+ Default value:
8
+ CSV::DEFAULT_OPTIONS.fetch(:liberal_parsing) # => false
9
+
10
+ For the next two examples:
11
+ str = 'is,this "three, or four",fields'
12
+
13
+ Without +liberal_parsing+:
14
+ # Raises CSV::MalformedCSVError (Illegal quoting in str 1.)
15
+ CSV.parse_line(str)
16
+
17
+ With +liberal_parsing+:
18
+ ary = CSV.parse_line(str, liberal_parsing: true)
19
+ ary # => ["is", "this \"three", " or four\"", "fields"]
20
+
21
+ Use the +backslash_quote+ sub-option to parse values that use
22
+ a backslash to escape a double-quote character. This
23
+ causes the parser to treat <code>\"</code> as if it were
24
+ <code>""</code>.
25
+
26
+ For the next two examples:
27
+ str = 'Show,"Harry \"Handcuff\" Houdini, the one and only","Tampa Theater"'
28
+
29
+ With +liberal_parsing+, but without the +backslash_quote+ sub-option:
30
+ # Incorrect interpretation of backslash; incorrectly interprets the quoted comma as a field separator.
31
+ ary = CSV.parse_line(str, liberal_parsing: true)
32
+ ary # => ["Show", "\"Harry \\\"Handcuff\\\" Houdini", " the one and only\"", "Tampa Theater"]
33
+ puts ary[1] # => "Harry \"Handcuff\" Houdini
34
+
35
+ With +liberal_parsing+ and its +backslash_quote+ sub-option:
36
+ ary = CSV.parse_line(str, liberal_parsing: { backslash_quote: true })
37
+ ary # => ["Show", "Harry \"Handcuff\" Houdini, the one and only", "Tampa Theater"]
38
+ puts ary[1] # => Harry "Handcuff" Houdini, the one and only
@@ -0,0 +1,12 @@
1
+ ====== Option +nil_value+
2
+
3
+ Specifies the object that is to be substituted for each null (no-text) field.
4
+
5
+ Default value:
6
+ CSV::DEFAULT_OPTIONS.fetch(:nil_value) # => nil
7
+
8
+ With the default, +nil+:
9
+ CSV.parse_line('a,,b,,c') # => ["a", nil, "b", nil, "c"]
10
+
11
+ With a different object:
12
+ CSV.parse_line('a,,b,,c', nil_value: 0) # => ["a", 0, "b", 0, "c"]
@@ -0,0 +1,22 @@
1
+ ====== Option +return_headers+
2
+
3
+ Specifies the boolean that determines whether method #shift
4
+ returns or ignores the header row.
5
+
6
+ Default value:
7
+ CSV::DEFAULT_OPTIONS.fetch(:return_headers) # => false
8
+
9
+ Examples:
10
+ str = <<-EOT
11
+ Name,Count
12
+ foo,0
13
+ bar,1
14
+ bax,2
15
+ EOT
16
+ # Without return_headers first row is str.
17
+ csv = CSV.new(str, headers: true)
18
+ csv.shift # => #<CSV::Row "Name":"foo" "Count":"0">
19
+ # With return_headers first row is headers.
20
+ csv = CSV.new(str, headers: true, return_headers: true)
21
+ csv.shift # => #<CSV::Row "Name":"Name" "Count":"Count">
22
+
@@ -0,0 +1,31 @@
1
+ ====== Option +skip_blanks+
2
+
3
+ Specifies a boolean that determines whether blank lines in the input will be ignored;
4
+ a line that contains a column separator is not considered to be blank.
5
+
6
+ Default value:
7
+ CSV::DEFAULT_OPTIONS.fetch(:skip_blanks) # => false
8
+
9
+ See also option {skiplines}[#class-CSV-label-Option+skip_lines].
10
+
11
+ For examples in this section:
12
+ str = <<-EOT
13
+ foo,0
14
+
15
+ bar,1
16
+ baz,2
17
+
18
+ ,
19
+ EOT
20
+
21
+ Using the default, +false+:
22
+ ary = CSV.parse(str)
23
+ ary # => [["foo", "0"], [], ["bar", "1"], ["baz", "2"], [], [nil, nil]]
24
+
25
+ Using +true+:
26
+ ary = CSV.parse(str, skip_blanks: true)
27
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]]
28
+
29
+ Using a truthy value:
30
+ ary = CSV.parse(str, skip_blanks: :foo)
31
+ ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"], [nil, nil]]