smarter_csv 1.0.16 → 1.0.17

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.
data/README.md CHANGED
@@ -135,6 +135,7 @@ The options and the block are optional.
135
135
  ---------------------------------------------------------------------------------------------------------------------------------
136
136
  | :col_sep | ',' | column separator |
137
137
  | :row_sep | $/ ,"\n" | row separator or record separator , defaults to system's $/ , which defaults to "\n" |
138
+ | | | this can also be set to :auto , but will process the whole cvs file first |
138
139
  | :quote_char | '"' | quotation character |
139
140
  | :comment_regexp | /^#/ | regular expression which matches comment lines (see NOTE about the CSV header) |
140
141
  | :chunk_size | nil | if set, determines the desired chunk-size (defaults to nil, no chunk processing) |
@@ -228,6 +229,9 @@ Or install it yourself as:
228
229
 
229
230
  ## Changes
230
231
 
232
+ #### 1.0.17 (2014-01-13)
233
+ * added option to set :row_sep to :auto , for automatic detection of the row-separator (issue #22)
234
+
231
235
  #### 1.0.16 (2014-01-13)
232
236
  * :convert_values_to_numeric option can now be qualified with :except or :only (thanks to Hugo Lepetit)
233
237
  * removed deprecated `process_csv` method
@@ -18,9 +18,14 @@ module SmarterCSV
18
18
  old_row_sep = $/
19
19
  line_count = 0
20
20
  begin
21
- $/ = options[:row_sep]
22
21
  f = input.respond_to?(:readline) ? input : File.open(input, "r:#{options[:file_encoding]}")
23
22
 
23
+ if options[:row_sep] == :auto
24
+ options[:row_sep] = SmarterCSV.guess_line_ending( f )
25
+ f.rewind
26
+ end
27
+ $/ = options[:row_sep]
28
+
24
29
  if options[:headers_in_file] # extract the header line
25
30
  # process the header line in the CSV file..
26
31
  # the first line of a CSV file contains the header .. it might be commented out, so we need to read it anyhow
@@ -185,5 +190,18 @@ module SmarterCSV
185
190
  end
186
191
  return false
187
192
  end
193
+
194
+ # limitation: this currently reads the whole file in before making a decision
195
+ def self.guess_line_ending( filehandle )
196
+ counts = {"\n" => 0 , "\r" => 0, "\r\n" => 0}
197
+
198
+ filehandle.each_char do |c|
199
+ next if c !~ /\r|\n|\r\n/
200
+ counts[c] += 1 # count how many of the pre-defined line-endings we find
201
+ end
202
+ # find the key/value pair with the largest counter:
203
+ k,v = counts.max_by{|k,v| v}
204
+ return k # the most frequent one is it
205
+ end
188
206
  end
189
207
 
@@ -1,3 +1,3 @@
1
1
  module SmarterCSV
2
- VERSION = "1.0.16"
2
+ VERSION = "1.0.17"
3
3
  end
@@ -0,0 +1,4 @@
1
+ name,count,price
2
+ hammer,4,12.50
3
+ axe,2,7.30
4
+ crowbar,3,17.50
@@ -0,0 +1 @@
1
+ name,count,price
@@ -0,0 +1,4 @@
1
+ name,count,price
2
+ hammer,4,12.50
3
+ axe,2,7.30
4
+ crowbar,3,17.50
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ fixture_path = 'spec/fixtures'
4
+
5
+ describe 'process files with line endings explicitly pre-specified' do
6
+ it 'reads file with \n line endings' do
7
+ options = {:row_sep => "\n"}
8
+ data = SmarterCSV.process("#{fixture_path}/line_endings_n.csv", options)
9
+ data.size.should == 3
10
+ end
11
+
12
+ it 'reads file with \r line endings' do
13
+ options = {:row_sep => "\r"}
14
+ data = SmarterCSV.process("#{fixture_path}/line_endings_r.csv", options)
15
+ data.size.should == 3
16
+ end
17
+
18
+ it 'reads file with \r\n line endings' do
19
+ options = {:row_sep => "\r\n"}
20
+ data = SmarterCSV.process("#{fixture_path}/line_endings_rn.csv", options)
21
+ data.size.should == 3
22
+ end
23
+ end
24
+
25
+ describe 'process files with line endings in automatic mode' do
26
+ it 'reads file with \n line endings' do
27
+ options = {:row_sep => :auto}
28
+ data = SmarterCSV.process("#{fixture_path}/line_endings_n.csv", options)
29
+ data.size.should == 3
30
+ end
31
+
32
+ it 'reads file with \r line endings' do
33
+ options = {:row_sep => :auto}
34
+ data = SmarterCSV.process("#{fixture_path}/line_endings_r.csv", options)
35
+ data.size.should == 3
36
+ end
37
+
38
+ it 'reads file with \r\n line endings' do
39
+ options = {:row_sep => :auto}
40
+ data = SmarterCSV.process("#{fixture_path}/line_endings_rn.csv", options)
41
+ data.size.should == 3
42
+ end
43
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smarter_csv
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.16
4
+ version: 1.0.17
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -55,6 +55,9 @@ files:
55
55
  - spec/fixtures/basic.csv
56
56
  - spec/fixtures/binary.csv
57
57
  - spec/fixtures/chunk_cornercase.csv
58
+ - spec/fixtures/line_endings_n.csv
59
+ - spec/fixtures/line_endings_r.csv
60
+ - spec/fixtures/line_endings_rn.csv
58
61
  - spec/fixtures/lots_of_columns.csv
59
62
  - spec/fixtures/no_header.csv
60
63
  - spec/fixtures/numeric.csv
@@ -67,6 +70,7 @@ files:
67
70
  - spec/smarter_csv/column_separator_spec.rb
68
71
  - spec/smarter_csv/convert_values_to_numeric_spec.rb
69
72
  - spec/smarter_csv/key_mapping_spec.rb
73
+ - spec/smarter_csv/line_ending_spec.rb
70
74
  - spec/smarter_csv/load_basic_spec.rb
71
75
  - spec/smarter_csv/no_header_spec.rb
72
76
  - spec/smarter_csv/not_downcase_header_spec.rb
@@ -112,6 +116,9 @@ test_files:
112
116
  - spec/fixtures/basic.csv
113
117
  - spec/fixtures/binary.csv
114
118
  - spec/fixtures/chunk_cornercase.csv
119
+ - spec/fixtures/line_endings_n.csv
120
+ - spec/fixtures/line_endings_r.csv
121
+ - spec/fixtures/line_endings_rn.csv
115
122
  - spec/fixtures/lots_of_columns.csv
116
123
  - spec/fixtures/no_header.csv
117
124
  - spec/fixtures/numeric.csv
@@ -124,6 +131,7 @@ test_files:
124
131
  - spec/smarter_csv/column_separator_spec.rb
125
132
  - spec/smarter_csv/convert_values_to_numeric_spec.rb
126
133
  - spec/smarter_csv/key_mapping_spec.rb
134
+ - spec/smarter_csv/line_ending_spec.rb
127
135
  - spec/smarter_csv/load_basic_spec.rb
128
136
  - spec/smarter_csv/no_header_spec.rb
129
137
  - spec/smarter_csv/not_downcase_header_spec.rb