csv 3.1.4 → 3.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/NEWS.md +18 -0
- data/doc/col_sep.rdoc +45 -0
- data/doc/converters.rdoc +45 -0
- data/doc/empty_value.rdoc +13 -0
- data/doc/field_size_limit.rdoc +39 -0
- data/doc/force_quotes.rdoc +17 -0
- data/doc/header_converters.rdoc +31 -0
- data/doc/headers.rdoc +63 -0
- data/doc/liberal_parsing.rdoc +19 -0
- data/doc/nil_value.rdoc +12 -0
- data/doc/quote_char.rdoc +32 -0
- data/doc/quote_empty.rdoc +12 -0
- data/doc/return_headers.rdoc +22 -0
- data/doc/row_sep.rdoc +91 -0
- data/doc/skip_blanks.rdoc +31 -0
- data/doc/skip_lines.rdoc +37 -0
- data/doc/strip.rdoc +15 -0
- data/doc/unconverted_fields.rdoc +27 -0
- data/doc/write_converters.rdoc +31 -0
- data/doc/write_empty_value.rdoc +15 -0
- data/doc/write_headers.rdoc +29 -0
- data/doc/write_nil_value.rdoc +14 -0
- data/lib/csv.rb +100 -26
- data/lib/csv/version.rb +1 -1
- metadata +29 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eec352a246dc1189213c78e35541e9903f172889792b92a23d6b8d7215d9ae37
|
4
|
+
data.tar.gz: 63754025784b9d6d26686b48efe8627b18c1aaa26e14f1261d14a09a4921612e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1b9895d4735d3f7a1376765d8e71a03388d4b8f52ace5a8eab3126e1f3167f77fcfd312212fdbdbda496d4a2f837a966bf33b871bee96f633c536b566ce0a9f
|
7
|
+
data.tar.gz: 9347baa988315b544d41ec23ded72a812dec09b7c0832c72bc4ff3be950e25d0f2184f9ed43967113ddb63e56e29c847bffb469b7883ad4207b913368057b58c
|
data/NEWS.md
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
## 3.1.5 - 2020-05-18
|
4
|
+
|
5
|
+
### Improvements
|
6
|
+
|
7
|
+
* Improved document.
|
8
|
+
[GitHub#124][Patch by Burdette Lamar]
|
9
|
+
|
10
|
+
### Fixes
|
11
|
+
|
12
|
+
* Added missing document files.
|
13
|
+
[GitHub#125][Reported by joast]
|
14
|
+
|
15
|
+
### Thanks
|
16
|
+
|
17
|
+
* Burdette Lamar
|
18
|
+
|
19
|
+
* joast
|
20
|
+
|
3
21
|
## 3.1.4 - 2020-05-17
|
4
22
|
|
5
23
|
### Improvements
|
data/doc/col_sep.rdoc
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
====== Option +col_sep+
|
2
|
+
|
3
|
+
Specifies the \String field 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
|
+
For examples in this section:
|
11
|
+
ary = ['a', 'b', 'c']
|
12
|
+
|
13
|
+
Using the default:
|
14
|
+
str = CSV.generate_line(line)
|
15
|
+
str # => "a,b,c\n"
|
16
|
+
ary = CSV.parse_line(str)
|
17
|
+
ary # => ["a", "b", "c"]
|
18
|
+
|
19
|
+
Using +:+ (colon):
|
20
|
+
col_sep = ':'
|
21
|
+
str = CSV.generate_line(ary, col_sep: col_sep)
|
22
|
+
str # => "a:b:c\n"
|
23
|
+
ary = CSV.parse_line(str, col_sep: col_sep)
|
24
|
+
ary # => [["a", "b", "c"]]
|
25
|
+
|
26
|
+
Using +::+ (two colons):
|
27
|
+
col_sep = '::'
|
28
|
+
str = CSV.generate_line(ary, col_sep: col_sep)
|
29
|
+
str # => "a::b::c\n"
|
30
|
+
ary = CSV.parse_line(str, col_sep: col_sep)
|
31
|
+
ary # => [["a", "b", "c"]]
|
32
|
+
|
33
|
+
---
|
34
|
+
|
35
|
+
Raises an exception if given the empty \String:
|
36
|
+
col_sep = ''
|
37
|
+
# Raises ArgumentError (:col_sep must be 1 or more characters: "")
|
38
|
+
CSV.parse_line("a:b:c\n", col_sep: col_sep)
|
39
|
+
|
40
|
+
Raises an exception if the given value is not String-convertible:
|
41
|
+
col_sep = BasicObject.new
|
42
|
+
# Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
|
43
|
+
CSV.generate_line(line, col_sep: col_sep)
|
44
|
+
# Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
|
45
|
+
CSV.parse(str, col_sep: col_sep)
|
data/doc/converters.rdoc
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
====== Option +converters+
|
2
|
+
|
3
|
+
Specifies a single field converter name or \Proc,
|
4
|
+
or an \Array of field converter names and Procs.
|
5
|
+
|
6
|
+
See {Field Converters}[#class-CSV-label-Field+Converters]
|
7
|
+
|
8
|
+
Default value:
|
9
|
+
CSV::DEFAULT_OPTIONS.fetch(:converters) # => nil
|
10
|
+
|
11
|
+
The value may be a single field converter name:
|
12
|
+
str = '1,2,3'
|
13
|
+
# Without a converter
|
14
|
+
ary = CSV.parse_line(str)
|
15
|
+
ary # => ["1", "2", "3"]
|
16
|
+
# With built-in converter :integer
|
17
|
+
ary = CSV.parse_line(str, converters: :integer)
|
18
|
+
ary # => [1, 2, 3]
|
19
|
+
|
20
|
+
The value may be an \Array of field converter names:
|
21
|
+
str = '1,3.14159'
|
22
|
+
# Without converters
|
23
|
+
ary = CSV.parse_line(str)
|
24
|
+
ary # => ["1", "3.14159"]
|
25
|
+
# With built-in converters
|
26
|
+
ary = CSV.parse_line(str, converters: [:integer, :float])
|
27
|
+
ary # => [1, 3.14159]
|
28
|
+
|
29
|
+
The value may be a \Proc custom converter:
|
30
|
+
str = ' foo , bar , baz '
|
31
|
+
# Without a converter
|
32
|
+
ary = CSV.parse_line(str)
|
33
|
+
ary # => [" foo ", " bar ", " baz "]
|
34
|
+
# With a custom converter
|
35
|
+
ary = CSV.parse_line(str, converters: proc {|field| field.strip })
|
36
|
+
ary # => ["foo", "bar", "baz"]
|
37
|
+
|
38
|
+
See also {Custom Converters}[#class-CSV-label-Custom+Converters]
|
39
|
+
|
40
|
+
---
|
41
|
+
|
42
|
+
Raises an exception if the converter is not a converter name or a \Proc:
|
43
|
+
str = 'foo,0'
|
44
|
+
# Raises NoMethodError (undefined method `arity' for nil:NilClass)
|
45
|
+
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,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,31 @@
|
|
1
|
+
====== Option +header_converters+
|
2
|
+
|
3
|
+
Specifies a \String converter name or an \Array of converter names.
|
4
|
+
|
5
|
+
Default value:
|
6
|
+
CSV::DEFAULT_OPTIONS.fetch(:header_converters) # => nil
|
7
|
+
|
8
|
+
Identical in functionality to option {converters}[#class-CSV-label-Option+converters]
|
9
|
+
except that:
|
10
|
+
- The converters apply only to the header row.
|
11
|
+
- The built-in header converters are +:downcase+ and +:symbol+.
|
12
|
+
|
13
|
+
Examples:
|
14
|
+
str = <<-EOT
|
15
|
+
foo,0
|
16
|
+
bar,1
|
17
|
+
baz,2
|
18
|
+
EOT
|
19
|
+
headers = ['Name', 'Value']
|
20
|
+
# With no header converter
|
21
|
+
csv = CSV.parse(str, headers: headers)
|
22
|
+
csv.headers # => ["Name", "Value"]
|
23
|
+
# With header converter :downcase
|
24
|
+
csv = CSV.parse(str, headers: headers, header_converters: :downcase)
|
25
|
+
csv.headers # => ["name", "value"]
|
26
|
+
# With header converter :symbol
|
27
|
+
csv = CSV.parse(str, headers: headers, header_converters: :symbol)
|
28
|
+
csv.headers # => [:name, :value]
|
29
|
+
# With both
|
30
|
+
csv = CSV.parse(str, headers: headers, header_converters: [:downcase, :symbol])
|
31
|
+
csv.headers # => [:name, :value]
|
data/doc/headers.rdoc
ADDED
@@ -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,19 @@
|
|
1
|
+
====== Option +liberal_parsing+
|
2
|
+
|
3
|
+
Specifies the boolean 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 examples in this section:
|
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"]
|
data/doc/nil_value.rdoc
ADDED
@@ -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"]
|
data/doc/quote_char.rdoc
ADDED
@@ -0,0 +1,32 @@
|
|
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) # => "\"" (backslash)
|
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:
|
14
|
+
ary = ['a', 'b', '"c"', 'd']
|
15
|
+
str = CSV.generate_line(ary)
|
16
|
+
str # => "a,b,\"\"\"c\"\"\",d\n"
|
17
|
+
ary = CSV.parse_line(str)
|
18
|
+
ary # => ["a", "b", "\"c\"", "d"]
|
19
|
+
|
20
|
+
Using <tt>'</tt> (single-quote):
|
21
|
+
quote_char = "'"
|
22
|
+
ary = ['a', 'b', '\'c\'', 'd']
|
23
|
+
str = CSV.generate_line(ary, quote_char: quote_char)
|
24
|
+
str # => "a,b,'''c''',d\n"
|
25
|
+
ary = CSV.parse_line(str, quote_char: quote_char)
|
26
|
+
ary # => [["a", "b", "'c'", "d"]]
|
27
|
+
|
28
|
+
---
|
29
|
+
|
30
|
+
Raises an exception if the \String length is greater than 1:
|
31
|
+
# Raises ArgumentError (:quote_char has to be nil or a single character String)
|
32
|
+
CSV.new('', quote_char: 'xx')
|
@@ -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,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
|
+
|
data/doc/row_sep.rdoc
ADDED
@@ -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
|
+
str = CSV.generate do |csv|
|
16
|
+
csv << [:foo, 0]
|
17
|
+
csv << [:bar, 1]
|
18
|
+
csv << [:baz, 2]
|
19
|
+
end
|
20
|
+
str # => "foo,0\nbar,1\nbaz,2\n"
|
21
|
+
ary = CSV.parse(str)
|
22
|
+
ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
|
23
|
+
|
24
|
+
Using <tt>|</tt> (pipe):
|
25
|
+
row_sep = '|'
|
26
|
+
str = CSV.generate(row_sep: row_sep) do |csv|
|
27
|
+
csv << [:foo, 0]
|
28
|
+
csv << [:bar, 1]
|
29
|
+
csv << [:baz, 2]
|
30
|
+
end
|
31
|
+
str # => "foo,0|bar,1|baz,2|"
|
32
|
+
ary = CSV.parse(str, row_sep: row_sep)
|
33
|
+
ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
|
34
|
+
|
35
|
+
Using <tt>--</tt> (two hyphens):
|
36
|
+
row_sep = '--'
|
37
|
+
str = CSV.generate(row_sep: row_sep) do |csv|
|
38
|
+
csv << [:foo, 0]
|
39
|
+
csv << [:bar, 1]
|
40
|
+
csv << [:baz, 2]
|
41
|
+
end
|
42
|
+
str # => "foo,0--bar,1--baz,2--"
|
43
|
+
ary = CSV.parse(str, row_sep: row_sep)
|
44
|
+
ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
|
45
|
+
|
46
|
+
Using <tt>''</tt> (empty string):
|
47
|
+
row_sep = ''
|
48
|
+
str = CSV.generate(row_sep: row_sep) do |csv|
|
49
|
+
csv << [:foo, 0]
|
50
|
+
csv << [:bar, 1]
|
51
|
+
csv << [:baz, 2]
|
52
|
+
end
|
53
|
+
str # => "foo,0bar,1baz,2"
|
54
|
+
ary = CSV.parse(str, row_sep: row_sep)
|
55
|
+
ary # => [["foo", "0bar", "1baz", "2"]]
|
56
|
+
|
57
|
+
---
|
58
|
+
|
59
|
+
When +row_sep+ is the \Symbol +:auto+ (the default),
|
60
|
+
invokes auto-discovery of the row separator.
|
61
|
+
|
62
|
+
Auto-discovery reads ahead in the data looking for the next <tt>\r\n</tt>, +\n+, or +\r+ sequence.
|
63
|
+
The sequence will be selected even if it occurs in a quoted field,
|
64
|
+
assuming that you would have the same line endings there.
|
65
|
+
|
66
|
+
row_sep = :auto
|
67
|
+
str = CSV.generate(row_sep: row_sep) do |csv|
|
68
|
+
csv << [:foo, 0]
|
69
|
+
csv << [:bar, 1]
|
70
|
+
csv << [:baz, 2]
|
71
|
+
end
|
72
|
+
str # => "foo,0\nbar,1\nbaz,2\n"
|
73
|
+
ary = CSV.parse(str, row_sep: row_sep)
|
74
|
+
ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
|
75
|
+
|
76
|
+
The default <tt>$INPUT_RECORD_SEPARATOR</tt> (<tt>$/</tt>) is used
|
77
|
+
if any of the following is true:
|
78
|
+
* None of those sequences is found.
|
79
|
+
* Data is +ARGF+, +STDIN+, +STDOUT+, or +STDERR+.
|
80
|
+
* The stream is only available for output.
|
81
|
+
|
82
|
+
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.
|
83
|
+
|
84
|
+
---
|
85
|
+
|
86
|
+
Raises an exception if the given value is not String-convertible:
|
87
|
+
row_sep = BasicObject.new
|
88
|
+
# Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
|
89
|
+
CSV.generate_line(ary, row_sep: row_sep)
|
90
|
+
# Raises NoMethodError (undefined method `to_s' for #<BasicObject:>)
|
91
|
+
CSV.parse(str, row_sep: row_sep)
|
@@ -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]]
|
data/doc/skip_lines.rdoc
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
====== Option +skip_lines+
|
2
|
+
|
3
|
+
Specifies an object to use in identifying comment lines in the input that are to be ignored:
|
4
|
+
* If a \Regexp, ignores lines that match it.
|
5
|
+
* If a \String, converts it to a \Regexp, ignores lines that match it.
|
6
|
+
* If +nil+, no lines are considered to be comments.
|
7
|
+
|
8
|
+
Default value:
|
9
|
+
CSV::DEFAULT_OPTIONS.fetch(:skip_lines) # => nil
|
10
|
+
|
11
|
+
For examples in this section:
|
12
|
+
str = <<-EOT
|
13
|
+
# Comment
|
14
|
+
foo,0
|
15
|
+
bar,1
|
16
|
+
baz,2
|
17
|
+
# Another comment
|
18
|
+
EOT
|
19
|
+
str # => "# Comment\nfoo,0\nbar,1\nbaz,2\n# Another comment\n"
|
20
|
+
|
21
|
+
Using the default, +nil+:
|
22
|
+
ary = CSV.parse(str)
|
23
|
+
ary # => [["# Comment"], ["foo", "0"], ["bar", "1"], ["baz", "2"], ["# Another comment"]]
|
24
|
+
|
25
|
+
Using a \Regexp:
|
26
|
+
ary = CSV.parse(str, skip_lines: /^#/)
|
27
|
+
ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
|
28
|
+
|
29
|
+
Using a \String:
|
30
|
+
ary = CSV.parse(str, skip_lines: '#')
|
31
|
+
ary # => [["foo", "0"], ["bar", "1"], ["baz", "2"]]
|
32
|
+
|
33
|
+
---
|
34
|
+
|
35
|
+
Raises an exception if given an object that is not a \Regexp, a \String, or +nil+:
|
36
|
+
# Raises ArgumentError (:skip_lines has to respond to #match: 0)
|
37
|
+
CSV.parse(str, skip_lines: 0)
|
data/doc/strip.rdoc
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
====== Option +strip+
|
2
|
+
|
3
|
+
Specifies the boolean value that determines whether
|
4
|
+
whitespace is stripped from each input field.
|
5
|
+
|
6
|
+
Default value:
|
7
|
+
CSV::DEFAULT_OPTIONS.fetch(:strip) # => false
|
8
|
+
|
9
|
+
With default value +false+:
|
10
|
+
ary = CSV.parse_line(' a , b ')
|
11
|
+
ary # => [" a ", " b "]
|
12
|
+
|
13
|
+
With value +true+:
|
14
|
+
ary = CSV.parse_line(' a , b ', strip: true)
|
15
|
+
ary # => ["a", "b"]
|
@@ -0,0 +1,27 @@
|
|
1
|
+
====== Option +unconverted_fields+
|
2
|
+
|
3
|
+
Specifies the boolean that determines whether unconverted field values are to be available.
|
4
|
+
|
5
|
+
Default value:
|
6
|
+
CSV::DEFAULT_OPTIONS.fetch(:unconverted_fields) # => nil
|
7
|
+
|
8
|
+
The unconverted field values are those found in the source data,
|
9
|
+
prior to any conversions performed via option +converters+.
|
10
|
+
|
11
|
+
When option +unconverted_fields+ is +true+,
|
12
|
+
each returned row (\Array or \CSV::Row) has an added method,
|
13
|
+
+unconverted_fields+, that returns the unconverted field values:
|
14
|
+
str = <<-EOT
|
15
|
+
foo,0
|
16
|
+
bar,1
|
17
|
+
baz,2
|
18
|
+
EOT
|
19
|
+
# Without unconverted_fields
|
20
|
+
csv = CSV.parse(str, converters: :integer)
|
21
|
+
csv # => [["foo", 0], ["bar", 1], ["baz", 2]]
|
22
|
+
csv.first.respond_to?(:unconverted_fields) # => false
|
23
|
+
# With unconverted_fields
|
24
|
+
csv = CSV.parse(str, converters: :integer, unconverted_fields: true)
|
25
|
+
csv # => [["foo", 0], ["bar", 1], ["baz", 2]]
|
26
|
+
csv.first.respond_to?(:unconverted_fields) # => true
|
27
|
+
csv.first.unconverted_fields # => ["foo", "0"]
|
@@ -0,0 +1,31 @@
|
|
1
|
+
====== Option +write_converters+
|
2
|
+
|
3
|
+
Specifies the \Proc or \Array of Procs that are to be called
|
4
|
+
for converting each output field.
|
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 = lambda {|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 = lambda {|field| field.upcase }
|
20
|
+
downcase_converter = lambda {|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
|
+
---
|
26
|
+
|
27
|
+
Raises an exception if the converter returns a value that is neither +nil+
|
28
|
+
nor \String-convertible:
|
29
|
+
bad_converter = lambda {|field| BasicObject.new }
|
30
|
+
# Raises NoMethodError (undefined method `is_a?' for #<BasicObject:>)
|
31
|
+
CSV.generate_line(['a', 'b', 'c'], write_converters: bad_converter)
|
@@ -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+ 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"
|
data/lib/csv.rb
CHANGED
@@ -109,7 +109,7 @@ using CSV::MatchP if CSV.const_defined?(:MatchP)
|
|
109
109
|
#
|
110
110
|
# The most generic interface of the library is:
|
111
111
|
#
|
112
|
-
# csv = CSV.new(
|
112
|
+
# csv = CSV.new(io, **options)
|
113
113
|
#
|
114
114
|
# # Reading: IO object should be open for read
|
115
115
|
# csv.read # => array of rows
|
@@ -809,19 +809,37 @@ class CSV
|
|
809
809
|
csv.string # return final String
|
810
810
|
end
|
811
811
|
|
812
|
+
# :call-seq:
|
813
|
+
# CSV.generate_line(ary)
|
814
|
+
# CSV.generate_line(ary, **options)
|
812
815
|
#
|
813
|
-
#
|
814
|
-
#
|
816
|
+
# Returns the \String created by generating \CSV from +ary+
|
817
|
+
# using the specified +options+.
|
815
818
|
#
|
816
|
-
#
|
819
|
+
# Argument +ary+ must be an \Array.
|
820
|
+
#
|
821
|
+
# Special options:
|
822
|
+
# * Option <tt>:row_sep</tt> defaults to <tt>$INPUT_RECORD_SEPARATOR</tt>
|
823
|
+
# (<tt>$/</tt>).:
|
824
|
+
# $INPUT_RECORD_SEPARATOR # => "\n"
|
825
|
+
# * This method accepts an additional option, <tt>:encoding</tt>, which sets the base
|
826
|
+
# Encoding for the output. This method will try to guess your Encoding from
|
827
|
+
# the first non-+nil+ field in +row+, if possible, but you may need to use
|
828
|
+
# this parameter as a backup plan.
|
829
|
+
#
|
830
|
+
# For other +options+,
|
831
|
+
# see {Options for Generating}[#class-CSV-label-Options+for+Generating].
|
817
832
|
#
|
818
|
-
#
|
819
|
-
# Encoding for the output. This method will try to guess your Encoding from
|
820
|
-
# the first non-+nil+ field in +row+, if possible, but you may need to use
|
821
|
-
# this parameter as a backup plan.
|
833
|
+
# ---
|
822
834
|
#
|
823
|
-
#
|
824
|
-
#
|
835
|
+
# Returns the \String generated from an \Array:
|
836
|
+
# CSV.generate_line(['foo', '0']) # => "foo,0\n"
|
837
|
+
#
|
838
|
+
# ---
|
839
|
+
#
|
840
|
+
# Raises an exception if +ary+ is not an \Array:
|
841
|
+
# # Raises NoMethodError (undefined method `find' for :foo:Symbol)
|
842
|
+
# CSV.generate_line(:foo)
|
825
843
|
#
|
826
844
|
def generate_line(row, **options)
|
827
845
|
options = {row_sep: $INPUT_RECORD_SEPARATOR}.merge(options)
|
@@ -955,12 +973,41 @@ class CSV
|
|
955
973
|
end
|
956
974
|
end
|
957
975
|
|
976
|
+
# :call-seq:
|
977
|
+
# CSV.parse_line(string)
|
978
|
+
# CSV.parse_line(io)
|
979
|
+
# CSV.parse_line(string, **options)
|
980
|
+
# CSV.parse_line(io, **options)
|
958
981
|
#
|
959
|
-
#
|
960
|
-
#
|
961
|
-
# first row is ignored.
|
982
|
+
# Returns the new \Array created by parsing the first line of +string+ or +io+
|
983
|
+
# using the specified +options+.
|
962
984
|
#
|
963
|
-
#
|
985
|
+
# Argument +string+ should be a \String object;
|
986
|
+
# it will be put into a new \StringIO object positioned at the beginning.
|
987
|
+
#
|
988
|
+
# Argument +io+ should be an \IO object; it will be positioned at the beginning.
|
989
|
+
#
|
990
|
+
# For +options+, see {Options for Parsing}[#class-CSV-label-Options+for+Parsing].
|
991
|
+
#
|
992
|
+
# ---
|
993
|
+
# Returns data from the first line from a String object:
|
994
|
+
# CSV.parse_line('foo,0') # => ["foo", "0"]
|
995
|
+
#
|
996
|
+
# Returns data from the first line from a File object:
|
997
|
+
# File.write('t.csv', 'foo,0')
|
998
|
+
# CSV.parse_line(File.open('t.csv')) # => ["foo", "0"]
|
999
|
+
#
|
1000
|
+
# Ignores lines after the first:
|
1001
|
+
# CSV.parse_line("foo,0\nbar,1\nbaz,2") # => ["foo", "0"]
|
1002
|
+
#
|
1003
|
+
# Returns +nil+ if the argument is an empty \String:
|
1004
|
+
# CSV.parse_line('') # => nil
|
1005
|
+
#
|
1006
|
+
# ---
|
1007
|
+
#
|
1008
|
+
# Raises an exception if the argument is +nil+:
|
1009
|
+
# # Raises ArgumentError (Cannot parse nil as CSV):
|
1010
|
+
# CSV.parse_line(nil)
|
964
1011
|
#
|
965
1012
|
def parse_line(line, **options)
|
966
1013
|
new(line, **options).each.first
|
@@ -1008,22 +1055,49 @@ class CSV
|
|
1008
1055
|
end
|
1009
1056
|
end
|
1010
1057
|
|
1058
|
+
# :call-seq:
|
1059
|
+
# CSV.new(string)
|
1060
|
+
# CSV.new(io)
|
1061
|
+
# CSV.new(string, **options)
|
1062
|
+
# CSV.new(io, **options)
|
1063
|
+
#
|
1064
|
+
# Returns the new \CSV object created using +string+ or +io+
|
1065
|
+
# and the specified +options+.
|
1066
|
+
#
|
1067
|
+
# Argument +string+ should be a \String object;
|
1068
|
+
# it will be put into a new \StringIO object positioned at the beginning.
|
1069
|
+
#
|
1070
|
+
# Argument +io+ should be an \IO object; it will be positioned at the beginning.
|
1071
|
+
#
|
1072
|
+
# To position at the end, for appending, use method CSV.generate.
|
1073
|
+
# For any other positioning, pass a preset StringIO object instead.
|
1074
|
+
#
|
1075
|
+
# In addition to the \CSV instance methods, several \IO
|
1076
|
+
# methods are delegated. See CSV::open for a complete list.
|
1077
|
+
#
|
1078
|
+
# For +options+, see:
|
1079
|
+
# * {Options for Parsing}[#class-CSV-label-Options+for+Parsing]
|
1080
|
+
# * {Options for Generating}[#class-CSV-label-Options+for+Generating]
|
1081
|
+
#
|
1082
|
+
# For performance reasons, the options cannot be overridden
|
1083
|
+
# in a \CSV object, so the options specified here will endure.
|
1084
|
+
#
|
1085
|
+
# ---
|
1011
1086
|
#
|
1012
|
-
#
|
1013
|
-
#
|
1014
|
-
#
|
1015
|
-
# a String for +data+, you can later retrieve it (after writing to it, for
|
1016
|
-
# example) with CSV.string().
|
1087
|
+
# Create a \CSV object from a \String object:
|
1088
|
+
# csv = CSV.new('foo,0')
|
1089
|
+
# csv # => #<CSV io_type:StringIO encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
|
1017
1090
|
#
|
1018
|
-
#
|
1019
|
-
#
|
1020
|
-
#
|
1091
|
+
# Create a \CSV object from a \File object:
|
1092
|
+
# File.write('t.csv', 'foo,0')
|
1093
|
+
# csv = CSV.new(File.open('t.csv'))
|
1094
|
+
# csv # => #<CSV io_type:File io_path:"t.csv" encoding:UTF-8 lineno:0 col_sep:"," row_sep:"\n" quote_char:"\"">
|
1021
1095
|
#
|
1022
|
-
#
|
1023
|
-
# and {Options for Generating}[#class-CSV-label-Options+for+Generating].
|
1096
|
+
# ---
|
1024
1097
|
#
|
1025
|
-
#
|
1026
|
-
#
|
1098
|
+
# Raises an exception if the argument is +nil+:
|
1099
|
+
# # Raises ArgumentError (Cannot parse nil as CSV):
|
1100
|
+
# CSV.new(nil)
|
1027
1101
|
#
|
1028
1102
|
def initialize(data,
|
1029
1103
|
col_sep: ",",
|
data/lib/csv/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: csv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.1.
|
4
|
+
version: 3.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Edward Gray II
|
@@ -75,11 +75,35 @@ email:
|
|
75
75
|
- kou@cozmixng.org
|
76
76
|
executables: []
|
77
77
|
extensions: []
|
78
|
-
extra_rdoc_files:
|
78
|
+
extra_rdoc_files:
|
79
|
+
- LICENSE.txt
|
80
|
+
- NEWS.md
|
81
|
+
- README.md
|
79
82
|
files:
|
80
83
|
- LICENSE.txt
|
81
84
|
- NEWS.md
|
82
85
|
- README.md
|
86
|
+
- doc/col_sep.rdoc
|
87
|
+
- doc/converters.rdoc
|
88
|
+
- doc/empty_value.rdoc
|
89
|
+
- doc/field_size_limit.rdoc
|
90
|
+
- doc/force_quotes.rdoc
|
91
|
+
- doc/header_converters.rdoc
|
92
|
+
- doc/headers.rdoc
|
93
|
+
- doc/liberal_parsing.rdoc
|
94
|
+
- doc/nil_value.rdoc
|
95
|
+
- doc/quote_char.rdoc
|
96
|
+
- doc/quote_empty.rdoc
|
97
|
+
- doc/return_headers.rdoc
|
98
|
+
- doc/row_sep.rdoc
|
99
|
+
- doc/skip_blanks.rdoc
|
100
|
+
- doc/skip_lines.rdoc
|
101
|
+
- doc/strip.rdoc
|
102
|
+
- doc/unconverted_fields.rdoc
|
103
|
+
- doc/write_converters.rdoc
|
104
|
+
- doc/write_empty_value.rdoc
|
105
|
+
- doc/write_headers.rdoc
|
106
|
+
- doc/write_nil_value.rdoc
|
83
107
|
- lib/csv.rb
|
84
108
|
- lib/csv/core_ext/array.rb
|
85
109
|
- lib/csv/core_ext/string.rb
|
@@ -96,7 +120,9 @@ licenses:
|
|
96
120
|
- BSD-2-Clause
|
97
121
|
metadata: {}
|
98
122
|
post_install_message:
|
99
|
-
rdoc_options:
|
123
|
+
rdoc_options:
|
124
|
+
- "--main"
|
125
|
+
- README.md
|
100
126
|
require_paths:
|
101
127
|
- lib
|
102
128
|
required_ruby_version: !ruby/object:Gem::Requirement
|