csv 3.0.0 → 3.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/NEWS.md +882 -0
- data/README.md +6 -3
- data/doc/csv/arguments/io.rdoc +5 -0
- data/doc/csv/options/common/col_sep.rdoc +57 -0
- data/doc/csv/options/common/quote_char.rdoc +42 -0
- data/doc/csv/options/common/row_sep.rdoc +91 -0
- data/doc/csv/options/generating/force_quotes.rdoc +17 -0
- data/doc/csv/options/generating/quote_empty.rdoc +12 -0
- data/doc/csv/options/generating/write_converters.rdoc +25 -0
- data/doc/csv/options/generating/write_empty_value.rdoc +15 -0
- data/doc/csv/options/generating/write_headers.rdoc +29 -0
- data/doc/csv/options/generating/write_nil_value.rdoc +14 -0
- data/doc/csv/options/parsing/converters.rdoc +46 -0
- data/doc/csv/options/parsing/empty_value.rdoc +13 -0
- data/doc/csv/options/parsing/field_size_limit.rdoc +39 -0
- data/doc/csv/options/parsing/header_converters.rdoc +43 -0
- data/doc/csv/options/parsing/headers.rdoc +63 -0
- data/doc/csv/options/parsing/liberal_parsing.rdoc +38 -0
- data/doc/csv/options/parsing/nil_value.rdoc +12 -0
- data/doc/csv/options/parsing/return_headers.rdoc +22 -0
- data/doc/csv/options/parsing/skip_blanks.rdoc +31 -0
- data/doc/csv/options/parsing/skip_lines.rdoc +37 -0
- data/doc/csv/options/parsing/strip.rdoc +15 -0
- data/doc/csv/options/parsing/unconverted_fields.rdoc +27 -0
- data/doc/csv/recipes/filtering.rdoc +158 -0
- data/doc/csv/recipes/generating.rdoc +298 -0
- data/doc/csv/recipes/parsing.rdoc +545 -0
- data/doc/csv/recipes/recipes.rdoc +6 -0
- data/lib/csv/core_ext/array.rb +1 -1
- data/lib/csv/core_ext/string.rb +1 -1
- data/lib/csv/fields_converter.rb +89 -0
- data/lib/csv/input_record_separator.rb +18 -0
- data/lib/csv/parser.rb +1288 -0
- data/lib/csv/row.rb +505 -136
- data/lib/csv/table.rb +791 -114
- data/lib/csv/version.rb +1 -1
- data/lib/csv/writer.rb +210 -0
- data/lib/csv.rb +2433 -1329
- metadata +66 -13
- data/news.md +0 -123
data/README.md
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# CSV
|
2
2
|
|
3
|
-
[](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 `
|
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]]
|