csv 1.0.2 → 3.2.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/NEWS.md +868 -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 +1290 -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 +2432 -1329
- metadata +66 -13
- 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 `
|
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]]
|