smarter_csv 1.1.5 → 1.12.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rspec +1 -2
- data/.rubocop.yml +154 -0
- data/CHANGELOG.md +364 -0
- data/CONTRIBUTORS.md +56 -0
- data/Gemfile +7 -2
- data/LICENSE.txt +21 -0
- data/README.md +44 -441
- data/Rakefile +39 -19
- data/TO_DO_v2.md +14 -0
- data/docs/_introduction.md +56 -0
- data/docs/basic_api.md +157 -0
- data/docs/batch_processing.md +68 -0
- data/docs/data_transformations.md +50 -0
- data/docs/examples.md +75 -0
- data/docs/header_transformations.md +113 -0
- data/docs/header_validations.md +36 -0
- data/docs/options.md +98 -0
- data/docs/row_col_sep.md +104 -0
- data/docs/value_converters.md +68 -0
- data/ext/smarter_csv/extconf.rb +14 -0
- data/ext/smarter_csv/smarter_csv.c +97 -0
- data/lib/smarter_csv/auto_detection.rb +78 -0
- data/lib/smarter_csv/errors.rb +16 -0
- data/lib/smarter_csv/file_io.rb +50 -0
- data/lib/smarter_csv/hash_transformations.rb +91 -0
- data/lib/smarter_csv/header_transformations.rb +63 -0
- data/lib/smarter_csv/header_validations.rb +34 -0
- data/lib/smarter_csv/headers.rb +68 -0
- data/lib/smarter_csv/options.rb +95 -0
- data/lib/smarter_csv/parser.rb +90 -0
- data/lib/smarter_csv/reader.rb +243 -0
- data/lib/smarter_csv/version.rb +3 -1
- data/lib/smarter_csv/writer.rb +116 -0
- data/lib/smarter_csv.rb +91 -3
- data/smarter_csv.gemspec +43 -20
- metadata +122 -137
- data/.gitignore +0 -8
- data/.travis.yml +0 -19
- data/lib/extensions/hash.rb +0 -7
- data/lib/smarter_csv/smarter_csv.rb +0 -281
- data/spec/fixtures/basic.csv +0 -8
- data/spec/fixtures/binary.csv +0 -1
- data/spec/fixtures/carriage_returns_n.csv +0 -18
- data/spec/fixtures/carriage_returns_quoted.csv +0 -3
- data/spec/fixtures/carriage_returns_r.csv +0 -1
- data/spec/fixtures/carriage_returns_rn.csv +0 -18
- data/spec/fixtures/chunk_cornercase.csv +0 -10
- data/spec/fixtures/empty.csv +0 -5
- data/spec/fixtures/line_endings_n.csv +0 -4
- data/spec/fixtures/line_endings_r.csv +0 -1
- data/spec/fixtures/line_endings_rn.csv +0 -4
- data/spec/fixtures/lots_of_columns.csv +0 -2
- data/spec/fixtures/malformed.csv +0 -3
- data/spec/fixtures/malformed_header.csv +0 -3
- data/spec/fixtures/money.csv +0 -3
- data/spec/fixtures/no_header.csv +0 -7
- data/spec/fixtures/numeric.csv +0 -5
- data/spec/fixtures/pets.csv +0 -5
- data/spec/fixtures/quoted.csv +0 -5
- data/spec/fixtures/separator.csv +0 -4
- data/spec/fixtures/skip_lines.csv +0 -8
- data/spec/fixtures/valid_unicode.csv +0 -5
- data/spec/fixtures/with_dashes.csv +0 -8
- data/spec/fixtures/with_dates.csv +0 -4
- data/spec/smarter_csv/binary_file2_spec.rb +0 -24
- data/spec/smarter_csv/binary_file_spec.rb +0 -22
- data/spec/smarter_csv/carriage_return_spec.rb +0 -170
- data/spec/smarter_csv/chunked_reading_spec.rb +0 -14
- data/spec/smarter_csv/close_file_spec.rb +0 -15
- data/spec/smarter_csv/column_separator_spec.rb +0 -11
- data/spec/smarter_csv/convert_values_to_numeric_spec.rb +0 -48
- data/spec/smarter_csv/extenstions_spec.rb +0 -17
- data/spec/smarter_csv/header_transformation_spec.rb +0 -21
- data/spec/smarter_csv/keep_headers_spec.rb +0 -24
- data/spec/smarter_csv/key_mapping_spec.rb +0 -25
- data/spec/smarter_csv/line_ending_spec.rb +0 -43
- data/spec/smarter_csv/load_basic_spec.rb +0 -20
- data/spec/smarter_csv/malformed_spec.rb +0 -21
- data/spec/smarter_csv/no_header_spec.rb +0 -24
- data/spec/smarter_csv/not_downcase_header_spec.rb +0 -24
- data/spec/smarter_csv/quoted_spec.rb +0 -23
- data/spec/smarter_csv/remove_empty_values_spec.rb +0 -13
- data/spec/smarter_csv/remove_keys_from_hashes_spec.rb +0 -25
- data/spec/smarter_csv/remove_not_mapped_keys_spec.rb +0 -35
- data/spec/smarter_csv/remove_values_matching_spec.rb +0 -26
- data/spec/smarter_csv/remove_zero_values_spec.rb +0 -25
- data/spec/smarter_csv/skip_lines_spec.rb +0 -29
- data/spec/smarter_csv/strings_as_keys_spec.rb +0 -24
- data/spec/smarter_csv/strip_chars_from_headers_spec.rb +0 -24
- data/spec/smarter_csv/valid_unicode_spec.rb +0 -94
- data/spec/smarter_csv/value_converters_spec.rb +0 -52
- data/spec/spec/spec_helper.rb +0 -17
- data/spec/spec.opts +0 -2
- data/spec/spec_helper.rb +0 -21
@@ -1,281 +0,0 @@
|
|
1
|
-
module SmarterCSV
|
2
|
-
|
3
|
-
class HeaderSizeMismatch < Exception; end
|
4
|
-
|
5
|
-
class IncorrectOption < Exception; end
|
6
|
-
|
7
|
-
def SmarterCSV.process(input, options={}, &block) # first parameter: filename or input object with readline method
|
8
|
-
default_options = {:col_sep => ',' , :row_sep => $/ , :quote_char => '"', :force_simple_split => false , :verbose => false ,
|
9
|
-
:remove_empty_values => true, :remove_zero_values => false , :remove_values_matching => nil , :remove_empty_hashes => true , :strip_whitespace => true,
|
10
|
-
:convert_values_to_numeric => true, :strip_chars_from_headers => nil , :user_provided_headers => nil , :headers_in_file => true,
|
11
|
-
:comment_regexp => /^#/, :chunk_size => nil , :key_mapping_hash => nil , :downcase_header => true, :strings_as_keys => false, :file_encoding => 'utf-8',
|
12
|
-
:remove_unmapped_keys => false, :keep_original_headers => false, :value_converters => nil, :skip_lines => nil, :force_utf8 => false, :invalid_byte_sequence => '',
|
13
|
-
:auto_row_sep_chars => 500
|
14
|
-
}
|
15
|
-
options = default_options.merge(options)
|
16
|
-
options[:invalid_byte_sequence] = '' if options[:invalid_byte_sequence].nil?
|
17
|
-
csv_options = options.select{|k,v| [:col_sep, :row_sep, :quote_char].include?(k)} # options.slice(:col_sep, :row_sep, :quote_char)
|
18
|
-
headerA = []
|
19
|
-
result = []
|
20
|
-
old_row_sep = $/
|
21
|
-
file_line_count = 0
|
22
|
-
csv_line_count = 0
|
23
|
-
begin
|
24
|
-
f = input.respond_to?(:readline) ? input : File.open(input, "r:#{options[:file_encoding]}")
|
25
|
-
|
26
|
-
if (options[:force_utf8] || options[:file_encoding] =~ /utf-8/i) && ( f.respond_to?(:external_encoding) && f.external_encoding != Encoding.find('UTF-8') || f.respond_to?(:encoding) && f.encoding != Encoding.find('UTF-8') )
|
27
|
-
puts 'WARNING: you are trying to process UTF-8 input, but did not open the input with "b:utf-8" option. See README file "NOTES about File Encodings".'
|
28
|
-
end
|
29
|
-
|
30
|
-
if options[:row_sep] == :auto
|
31
|
-
options[:row_sep] = line_ending = SmarterCSV.guess_line_ending( f, options )
|
32
|
-
f.rewind
|
33
|
-
end
|
34
|
-
$/ = options[:row_sep]
|
35
|
-
|
36
|
-
if options[:skip_lines].to_i > 0
|
37
|
-
options[:skip_lines].to_i.times{f.readline}
|
38
|
-
end
|
39
|
-
|
40
|
-
if options[:headers_in_file] # extract the header line
|
41
|
-
# process the header line in the CSV file..
|
42
|
-
# the first line of a CSV file contains the header .. it might be commented out, so we need to read it anyhow
|
43
|
-
header = f.readline
|
44
|
-
header = header.force_encoding('utf-8').encode('utf-8', invalid: :replace, undef: :replace, replace: options[:invalid_byte_sequence]) if options[:force_utf8] || options[:file_encoding] !~ /utf-8/i
|
45
|
-
header = header.sub(options[:comment_regexp],'').chomp(options[:row_sep])
|
46
|
-
|
47
|
-
file_line_count += 1
|
48
|
-
csv_line_count += 1
|
49
|
-
header = header.gsub(options[:strip_chars_from_headers], '') if options[:strip_chars_from_headers]
|
50
|
-
|
51
|
-
if (header =~ %r{#{options[:quote_char]}}) and (! options[:force_simple_split])
|
52
|
-
file_headerA = begin
|
53
|
-
CSV.parse( header, csv_options ).flatten.collect!{|x| x.nil? ? '' : x} # to deal with nil values from CSV.parse
|
54
|
-
rescue CSV::MalformedCSVError => e
|
55
|
-
raise $!, "#{$!} [SmarterCSV: csv line #{csv_line_count}]", $!.backtrace
|
56
|
-
end
|
57
|
-
else
|
58
|
-
file_headerA = header.split(options[:col_sep])
|
59
|
-
end
|
60
|
-
file_headerA.map!{|x| x.gsub(%r/options[:quote_char]/,'') }
|
61
|
-
file_headerA.map!{|x| x.strip} if options[:strip_whitespace]
|
62
|
-
unless options[:keep_original_headers]
|
63
|
-
file_headerA.map!{|x| x.gsub(/\s+|-+/,'_')}
|
64
|
-
file_headerA.map!{|x| x.downcase } if options[:downcase_header]
|
65
|
-
end
|
66
|
-
|
67
|
-
file_header_size = file_headerA.size
|
68
|
-
else
|
69
|
-
raise SmarterCSV::IncorrectOption , "ERROR [smarter_csv]: If :headers_in_file is set to false, you have to provide :user_provided_headers" if options[:user_provided_headers].nil?
|
70
|
-
end
|
71
|
-
if options[:user_provided_headers] && options[:user_provided_headers].class == Array && ! options[:user_provided_headers].empty?
|
72
|
-
# use user-provided headers
|
73
|
-
headerA = options[:user_provided_headers]
|
74
|
-
if defined?(file_header_size) && ! file_header_size.nil?
|
75
|
-
if headerA.size != file_header_size
|
76
|
-
raise SmarterCSV::HeaderSizeMismatch , "ERROR [smarter_csv]: :user_provided_headers defines #{headerA.size} headers != CSV-file #{input} has #{file_header_size} headers"
|
77
|
-
else
|
78
|
-
# we could print out the mapping of file_headerA to headerA here
|
79
|
-
end
|
80
|
-
end
|
81
|
-
else
|
82
|
-
headerA = file_headerA
|
83
|
-
end
|
84
|
-
headerA.map!{|x| x.to_sym } unless options[:strings_as_keys] || options[:keep_original_headers]
|
85
|
-
|
86
|
-
unless options[:user_provided_headers] # wouldn't make sense to re-map user provided headers
|
87
|
-
key_mappingH = options[:key_mapping]
|
88
|
-
|
89
|
-
# do some key mapping on the keys in the file header
|
90
|
-
# if you want to completely delete a key, then map it to nil or to ''
|
91
|
-
if ! key_mappingH.nil? && key_mappingH.class == Hash && key_mappingH.keys.size > 0
|
92
|
-
headerA.map!{|x| key_mappingH.has_key?(x) ? (key_mappingH[x].nil? ? nil : key_mappingH[x].to_sym) : (options[:remove_unmapped_keys] ? nil : x)}
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
# in case we use chunking.. we'll need to set it up..
|
97
|
-
if ! options[:chunk_size].nil? && options[:chunk_size].to_i > 0
|
98
|
-
use_chunks = true
|
99
|
-
chunk_size = options[:chunk_size].to_i
|
100
|
-
chunk_count = 0
|
101
|
-
chunk = []
|
102
|
-
else
|
103
|
-
use_chunks = false
|
104
|
-
end
|
105
|
-
|
106
|
-
# now on to processing all the rest of the lines in the CSV file:
|
107
|
-
while ! f.eof? # we can't use f.readlines() here, because this would read the whole file into memory at once, and eof => true
|
108
|
-
line = f.readline # read one line.. this uses the input_record_separator $/ which we set previously!
|
109
|
-
|
110
|
-
# replace invalid byte sequence in UTF-8 with question mark to avoid errors
|
111
|
-
line = line.force_encoding('utf-8').encode('utf-8', invalid: :replace, undef: :replace, replace: options[:invalid_byte_sequence]) if options[:force_utf8] || options[:file_encoding] !~ /utf-8/i
|
112
|
-
|
113
|
-
file_line_count += 1
|
114
|
-
csv_line_count += 1
|
115
|
-
print "processing file line %10d, csv line %10d\r" % [file_line_count, csv_line_count] if options[:verbose]
|
116
|
-
next if line =~ options[:comment_regexp] # ignore all comment lines if there are any
|
117
|
-
|
118
|
-
# cater for the quoted csv data containing the row separator carriage return character
|
119
|
-
# in which case the row data will be split across multiple lines (see the sample content in spec/fixtures/carriage_returns_rn.csv)
|
120
|
-
# by detecting the existence of an uneven number of quote characters
|
121
|
-
multiline = line.count(options[:quote_char])%2 == 1
|
122
|
-
while line.count(options[:quote_char])%2 == 1
|
123
|
-
next_line = f.readline
|
124
|
-
next_line = next_line.force_encoding('utf-8').encode('utf-8', invalid: :replace, undef: :replace, replace: options[:invalid_byte_sequence]) if options[:force_utf8] || options[:file_encoding] !~ /utf-8/i
|
125
|
-
line += next_line
|
126
|
-
file_line_count += 1
|
127
|
-
end
|
128
|
-
print "\nline contains uneven number of quote chars so including content through file line %d\n" % file_line_count if options[:verbose] && multiline
|
129
|
-
|
130
|
-
line.chomp! # will use $/ which is set to options[:col_sep]
|
131
|
-
|
132
|
-
if (line =~ %r{#{options[:quote_char]}}) and (! options[:force_simple_split])
|
133
|
-
dataA = begin
|
134
|
-
CSV.parse( line, csv_options ).flatten.collect!{|x| x.nil? ? '' : x} # to deal with nil values from CSV.parse
|
135
|
-
rescue CSV::MalformedCSVError => e
|
136
|
-
raise $!, "#{$!} [SmarterCSV: csv line #{csv_line_count}]", $!.backtrace
|
137
|
-
end
|
138
|
-
else
|
139
|
-
dataA = line.split(options[:col_sep])
|
140
|
-
end
|
141
|
-
dataA.map!{|x| x.gsub(%r/options[:quote_char]/,'') }
|
142
|
-
dataA.map!{|x| x.strip} if options[:strip_whitespace]
|
143
|
-
hash = Hash.zip(headerA,dataA) # from Facets of Ruby library
|
144
|
-
# make sure we delete any key/value pairs from the hash, which the user wanted to delete:
|
145
|
-
# Note: Ruby < 1.9 doesn't allow empty symbol literals!
|
146
|
-
hash.delete(nil); hash.delete('');
|
147
|
-
if RUBY_VERSION.to_f > 1.8
|
148
|
-
eval('hash.delete(:"")')
|
149
|
-
end
|
150
|
-
|
151
|
-
# remove empty values using the same regexp as used by the rails blank? method
|
152
|
-
# which caters for double \n and \r\n characters such as "1\r\n\r\n2" whereas the original check (v =~ /^\s*$/) does not
|
153
|
-
hash.delete_if{|k,v| v.nil? || v !~ /[^[:space:]]/} if options[:remove_empty_values]
|
154
|
-
|
155
|
-
hash.delete_if{|k,v| ! v.nil? && v =~ /^(\d+|\d+\.\d+)$/ && v.to_f == 0} if options[:remove_zero_values] # values are typically Strings!
|
156
|
-
hash.delete_if{|k,v| v =~ options[:remove_values_matching]} if options[:remove_values_matching]
|
157
|
-
if options[:convert_values_to_numeric]
|
158
|
-
hash.each do |k,v|
|
159
|
-
# deal with the :only / :except options to :convert_values_to_numeric
|
160
|
-
next if SmarterCSV.only_or_except_limit_execution( options, :convert_values_to_numeric , k )
|
161
|
-
|
162
|
-
# convert if it's a numeric value:
|
163
|
-
case v
|
164
|
-
when /^[+-]?\d+\.\d+$/
|
165
|
-
hash[k] = v.to_f
|
166
|
-
when /^[+-]?\d+$/
|
167
|
-
hash[k] = v.to_i
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
|
172
|
-
if options[:value_converters]
|
173
|
-
hash.each do |k,v|
|
174
|
-
converter = options[:value_converters][k]
|
175
|
-
next unless converter
|
176
|
-
hash[k] = converter.convert(v)
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
next if hash.empty? if options[:remove_empty_hashes]
|
181
|
-
|
182
|
-
if use_chunks
|
183
|
-
chunk << hash # append temp result to chunk
|
184
|
-
|
185
|
-
if chunk.size >= chunk_size || f.eof? # if chunk if full, or EOF reached
|
186
|
-
# do something with the chunk
|
187
|
-
if block_given?
|
188
|
-
yield chunk # do something with the hashes in the chunk in the block
|
189
|
-
else
|
190
|
-
result << chunk # not sure yet, why anybody would want to do this without a block
|
191
|
-
end
|
192
|
-
chunk_count += 1
|
193
|
-
chunk = [] # initialize for next chunk of data
|
194
|
-
else
|
195
|
-
|
196
|
-
# the last chunk may contain partial data, which also needs to be returned (BUG / ISSUE-18)
|
197
|
-
|
198
|
-
end
|
199
|
-
|
200
|
-
# while a chunk is being filled up we don't need to do anything else here
|
201
|
-
|
202
|
-
else # no chunk handling
|
203
|
-
if block_given?
|
204
|
-
yield [hash] # do something with the hash in the block (better to use chunking here)
|
205
|
-
else
|
206
|
-
result << hash
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
# print new line to retain last processing line message
|
212
|
-
print "\n" if options[:verbose]
|
213
|
-
|
214
|
-
# last chunk:
|
215
|
-
if ! chunk.nil? && chunk.size > 0
|
216
|
-
# do something with the chunk
|
217
|
-
if block_given?
|
218
|
-
yield chunk # do something with the hashes in the chunk in the block
|
219
|
-
else
|
220
|
-
result << chunk # not sure yet, why anybody would want to do this without a block
|
221
|
-
end
|
222
|
-
chunk_count += 1
|
223
|
-
chunk = [] # initialize for next chunk of data
|
224
|
-
end
|
225
|
-
ensure
|
226
|
-
$/ = old_row_sep # make sure this stupid global variable is always reset to it's previous value after we're done!
|
227
|
-
f.close
|
228
|
-
end
|
229
|
-
if block_given?
|
230
|
-
return chunk_count # when we do processing through a block we only care how many chunks we processed
|
231
|
-
else
|
232
|
-
return result # returns either an Array of Hashes, or an Array of Arrays of Hashes (if in chunked mode)
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
private
|
237
|
-
# acts as a road-block to limit processing when iterating over all k/v pairs of a CSV-hash:
|
238
|
-
|
239
|
-
def self.only_or_except_limit_execution( options, option_name, key )
|
240
|
-
if options[option_name].is_a?(Hash)
|
241
|
-
if options[option_name].has_key?( :except )
|
242
|
-
return true if Array( options[ option_name ][:except] ).include?(key)
|
243
|
-
elsif options[ option_name ].has_key?(:only)
|
244
|
-
return true unless Array( options[ option_name ][:only] ).include?(key)
|
245
|
-
end
|
246
|
-
end
|
247
|
-
return false
|
248
|
-
end
|
249
|
-
|
250
|
-
# limitation: this currently reads the whole file in before making a decision
|
251
|
-
def self.guess_line_ending( filehandle, options )
|
252
|
-
counts = {"\n" => 0 , "\r" => 0, "\r\n" => 0}
|
253
|
-
quoted_char = false
|
254
|
-
|
255
|
-
# count how many of the pre-defined line-endings we find
|
256
|
-
# ignoring those contained within quote characters
|
257
|
-
last_char = nil
|
258
|
-
lines = 0
|
259
|
-
filehandle.each_char do |c|
|
260
|
-
quoted_char = !quoted_char if c == options[:quote_char]
|
261
|
-
next if quoted_char
|
262
|
-
|
263
|
-
if last_char == "\r"
|
264
|
-
if c == "\n"
|
265
|
-
counts["\r\n"] += 1
|
266
|
-
else
|
267
|
-
counts["\r"] += 1 # \r are counted after they appeared, we might
|
268
|
-
end
|
269
|
-
elsif c == "\n"
|
270
|
-
counts["\n"] += 1
|
271
|
-
end
|
272
|
-
last_char = c
|
273
|
-
lines += 1
|
274
|
-
break if options[:auto_row_sep_chars] && options[:auto_row_sep_chars] > 0 && lines >= options[:auto_row_sep_chars]
|
275
|
-
end
|
276
|
-
counts["\r"] += 1 if last_char == "\r"
|
277
|
-
# find the key/value pair with the largest counter:
|
278
|
-
k,_ = counts.max_by{|_,v| v}
|
279
|
-
return k # the most frequent one is it
|
280
|
-
end
|
281
|
-
end
|
data/spec/fixtures/basic.csv
DELETED
data/spec/fixtures/binary.csv
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
#timestampitem_idparent_idname#some comments here#these can be multiple comments in the header section#even more comments here1381388409101Thing 11381388409111Thing 21381388409121Thing 313813884091Parent 113813884092Parent 21381388409202Thing 41381388409212Thing 51381388409222Thing 6
|
@@ -1,18 +0,0 @@
|
|
1
|
-
Name,Street,City
|
2
|
-
Anfield,Anfield Road,Liverpool
|
3
|
-
"Highbury
|
4
|
-
Highbury House",75 Drayton Park,London
|
5
|
-
Old Trafford,"Sir Matt
|
6
|
-
Busby Way",Manchester
|
7
|
-
St. James' Park,,"Newcastle-upon-tyne
|
8
|
-
Tyne and Wear"
|
9
|
-
"White Hart Lane
|
10
|
-
(The Lane)","Bill Nicholson Way
|
11
|
-
748 High Rd","Tottenham
|
12
|
-
London"
|
13
|
-
Stamford Bridge,"Fulham Road
|
14
|
-
London",
|
15
|
-
"Etihad Stadium
|
16
|
-
Rowsley St
|
17
|
-
Manchester",,
|
18
|
-
Goodison,Goodison Road,Liverpool
|
@@ -1 +0,0 @@
|
|
1
|
-
Name,Street,City
|
@@ -1,18 +0,0 @@
|
|
1
|
-
Name,Street,City
|
2
|
-
Anfield,Anfield Road,Liverpool
|
3
|
-
"Highbury
|
4
|
-
Highbury House",75 Drayton Park,London
|
5
|
-
Old Trafford,"Sir Matt
|
6
|
-
Busby Way",Manchester
|
7
|
-
St. James' Park,,"Newcastle-upon-tyne
|
8
|
-
Tyne and Wear"
|
9
|
-
"White Hart Lane
|
10
|
-
(The Lane)","Bill Nicholson Way
|
11
|
-
748 High Rd","Tottenham
|
12
|
-
London"
|
13
|
-
Stamford Bridge,"Fulham Road
|
14
|
-
London",
|
15
|
-
"Etihad Stadium
|
16
|
-
Rowsley St
|
17
|
-
Manchester",,
|
18
|
-
Goodison,Goodison Road,Liverpool
|
data/spec/fixtures/empty.csv
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
name,count,price
|
@@ -1,2 +0,0 @@
|
|
1
|
-
Column 0,Column 1,Column 2,Column 3,Column 4,Column 5,Column 6,Column 7,Column 8,Column 9,Column 10,Column 11,Column 12,Column 13,Column 14,Column 15,Column 16,Column 17,Column 18,Column 19,Column 20,Column 21,Column 22,Column 23,Column 24,Column 25,Column 26,Column 27,Column 28,Column 29,Column 30,Column 31,Column 32,Column 33,Column 34,Column 35,Column 36,Column 37,Column 38,Column 39,Column 40,Column 41,Column 42,Column 43,Column 44,Column 45,Column 46,Column 47,Column 48,Column 49,Column 50,Column 51,Column 52,Column 53,Column 54,Column 55,Column 56,Column 57,Column 58,Column 59,Column 60,Column 61,Column 62,Column 63,Column 64,Column 65,Column 66,Column 67,Column 68,Column 69,Column 70,Column 71,Column 72,Column 73,Column 74,Column 75,Column 76,Column 77,Column 78,Column 79,Column 80,Column 81,Column 82,Column 83,Column 84,Column 85,Column 86,Column 87,Column 88,Column 89,Column 90,Column 91,Column 92,Column 93,Column 94,Column 95,Column 96,Column 97,Column 98,Column 99,Column 100,Column 101,Column 102,Column 103,Column 104,Column 105,Column 106,Column 107,Column 108,Column 109,Column 110,Column 111,Column 112,Column 113,Column 114,Column 115,Column 116,Column 117,Column 118,Column 119,Column 120,Column 121,Column 122,Column 123,Column 124,Column 125,Column 126,Column 127,Column 128,Column 129,Column 130,Column 131,Column 132,Column 133,Column 134,Column 135,Column 136,Column 137,Column 138,Column 139,Column 140,Column 141,Column 142,Column 143,Column 144,Column 145,Column 146,Column 147,Column 148,Column 149,Column 150,Column 151,Column 152,Column 153,Column 154,Column 155,Column 156,Column 157,Column 158,Column 159,Column 160,Column 161,Column 162,Column 163,Column 164,Column 165,Column 166,Column 167,Column 168,Column 169,Column 170,Column 171,Column 172,Column 173,Column 174,Column 175,Column 176,Column 177,Column 178,Column 179,Column 180,Column 181,Column 182,Column 183,Column 184,Column 185,Column 186,Column 187,Column 188,Column 189,Column 190,Column 191,Column 192,Column 193,Column 194,Column 195,Column 196,Column 197,Column 198,Column 199,Column 200,Column 201,Column 202,Column 203,Column 204,Column 205,Column 206,Column 207,Column 208,Column 209,Column 210,Column 211,Column 212,Column 213,Column 214,Column 215,Column 216,Column 217,Column 218,Column 219,Column 220,Column 221,Column 222,Column 223,Column 224,Column 225,Column 226,Column 227,Column 228,Column 229,Column 230,Column 231,Column 232,Column 233,Column 234,Column 235,Column 236,Column 237,Column 238,Column 239,Column 240,Column 241,Column 242,Column 243,Column 244,Column 245,Column 246,Column 247,Column 248,Column 249,Column 250,Column 251,Column 252,Column 253,Column 254,Column 255,Column 256,Column 257,Column 258,Column 259,Column 260,Column 261,Column 262,Column 263,Column 264,Column 265,Column 266,Column 267,Column 268,Column 269,Column 270,Column 271,Column 272,Column 273,Column 274,Column 275,Column 276,Column 277,Column 278,Column 279,Column 280,Column 281,Column 282,Column 283,Column 284,Column 285,Column 286,Column 287,Column 288,Column 289,Column 290,Column 291,Column 292,Column 293,Column 294,Column 295,Column 296,Column 297,Column 298,Column 299,Column 300,Column 301,Column 302,Column 303,Column 304,Column 305,Column 306,Column 307,Column 308,Column 309,Column 310,Column 311,Column 312,Column 313,Column 314,Column 315,Column 316,Column 317,Column 318,Column 319,Column 320,Column 321,Column 322,Column 323,Column 324,Column 325,Column 326,Column 327,Column 328,Column 329,Column 330,Column 331,Column 332,Column 333,Column 334,Column 335,Column 336,Column 337,Column 338,Column 339,Column 340,Column 341,Column 342,Column 343,Column 344,Column 345,Column 346,Column 347,Column 348,Column 349,Column 350,Column 351,Column 352,Column 353,Column 354,Column 355,Column 356,Column 357,Column 358,Column 359,Column 360,Column 361,Column 362,Column 363,Column 364,Column 365,Column 366,Column 367,Column 368,Column 369,Column 370,Column 371,Column 372,Column 373,Column 374,Column 375,Column 376,Column 377,Column 378,Column 379,Column 380,Column 381,Column 382,Column 383,Column 384,Column 385,Column 386,Column 387,Column 388,Column 389,Column 390,Column 391,Column 392,Column 393,Column 394,Column 395,Column 396,Column 397,Column 398,Column 399,Column 400,Column 401,Column 402,Column 403,Column 404,Column 405,Column 406,Column 407,Column 408,Column 409,Column 410,Column 411,Column 412,Column 413,Column 414,Column 415,Column 416,Column 417,Column 418,Column 419,Column 420,Column 421,Column 422,Column 423,Column 424,Column 425,Column 426,Column 427,Column 428,Column 429,Column 430,Column 431,Column 432,Column 433,Column 434,Column 435,Column 436,Column 437,Column 438,Column 439,Column 440,Column 441,Column 442,Column 443,Column 444,Column 445,Column 446,Column 447,Column 448,Column 449,Column 450,Column 451,Column 452,Column 453,Column 454,Column 455,Column 456,Column 457,Column 458,Column 459,Column 460,Column 461,Column 462,Column 463,Column 464,Column 465,Column 466,Column 467,Column 468,Column 469,Column 470,Column 471,Column 472,Column 473,Column 474,Column 475,Column 476,Column 477,Column 478,Column 479,Column 480,Column 481,Column 482,Column 483,Column 484,Column 485,Column 486,Column 487,Column 488,Column 489,Column 490,Column 491,Column 492,Column 493,Column 494,Column 495,Column 496,Column 497,Column 498,Column 499
|
2
|
-
rFDAsZLKkINpb,ChLVlxWpwZfrOZg,uGJbxzrFncG,R,P,j,QoKRekBnucMA,N,KJFTwrG,Fs,pKazVnOVFnLvAcK,bo,EgJwvAwnGYPdvj,qVPGxupPKQI,FtNJBxxMIBxezfS,,qrcOm,Angkc,kwhJvozx,H,Yk,Bs,JZTVzstyk,sDiZuoBOVPA,hsgzXcqSnUaF,,AMQcprcuLABRvLF,NxwQvVApPdtTJSw,tKjftA,lOyqAtUuXQtK,ImgNiMBPRo,dyVW,dVbtwSuZuX,IQN,pUEEshP,QVKcImQ,HDoRZ,jrQpVdvtjGHv,YkP,dHyjESzVsgUdRh,p,qz,oCP,clMCAiuiw,JzxVq,zpn,bwfoYmrJkTc,t,HGYcQdMmNjb,CFFbJTeOozA,,MwroljZZwEoBOoc,,wkIRXssJZ,LSaIDarn,qky,BDMJVYE,thOpnBTTiGMfa,JVhoOwTdoukH,xIECafnWcE,,,kbxzc,viKcs,dwVMljnI,fYXJYw,PhohmrDa,alGbl,aeqwrXgjr,MJ,gapeNlzKYUP,tys,PJPfxFYYFPclGJV,HIUXf,AjmDljNZjYqB,HbxoDVzzkQ,aLQFk,PormYxT,rATMrIlCFrDwOzD,Krv,pMwcHztVfVkKo,srb,fdlXgWtPK,r,UZvVNkLYigVzZO,RPDHskEaMqq,dVkUXNKFRbwq,FGSqF,mqG,aZzufH,LHsN,NkKlcjoRFTbFH,ChEHvIQDYomC,L,URFkXirNgU,M,gAtCyH,FLkbLzwEBLgtlt,OadGQgGxGqGkT,tEQUWJDpb,p,fXIyPxIftbgHNPL,dM,mrz,cGXxRFLUG,MMvNyk,mKEcw,QMROkjgOWnBSZI,DQQ,QeKZt,Xaor,KUPKflOhGnrOMu,VpwHZUN,raDbObrwsRaa,,WqddHDTh,wj,XZtQIS,CGPUgYOQtiu,,zRkl,,ATlS,JheeokutCEtvAdV,hozEKLGRET,DsEiWDjQ,lTQjDhEah,WqREQoJLBSP,,FOaImBDZclTMM,vhEjpJddIVh,xC,ZCSpDtdJw,phRxoGO,VdhVyRebsNynrk,HfCkVLQnLnRLA,dwxQUCPZc,koFg,lumNQmIweYyTc,R,bDRcfIO,cxH,n,navCHjPdfj,puDQpjuIIMRDqK,EVkAd,ARVpVku,hUEqyejzKt,,Qtygnqk,HlZgSRnbmIHZP,QZpVTn,OQgoIZhxIsh,TYPUMV,ofjg,YvYMWpSOAA,PGtCCHInmFBqPp,va,viWLIIjBOEwQCP,E,yjKVemUmGC,FQhSaVdeAJjO,flcBAZzLOlrg,bShmRGHdOemzMZi,gjUzxDONxWymoK,ZS,VBFVHug,igVYBKUJIcGKbim,msrUQUHTNymL,,pVeEHwNN,BqnU,UkYsIhEnqayMIa,RQHqYCoEU,ujuLHy,DctKlTNlADp,MJmfaBxeNIONUTQ,BcPqmfBSWJEs,kH,bYQiLOweBh,ajEmwTPgdGtDI,aeMJiQthn,QfvLiAuJjYB,aNauvl,bcCqdQie,tCwTqF,tNVw,sbjLwbktZUM,Mkrlh,sQihM,clRevuPt,weuxLMDulNP,juaeGRXAz,SKenpQsEZqAA,UGdQdLHvOH,brBHqPjs,WLS,fZ,DBSBUMvgLYzbKH,eFks,zLt,hqnDnIsUsremb,dizzYLAKUGXsH,vDWNIbiepsMPPm,QHNpZgZ,vl,KpukrVVjLDll,rbOPLzI,woALqQUQnt,JiG,SGZGCjPyvceLmy,ofcCQgXjgVmRsxV,,EERhEDO,PxuJxrOka,ohMLIz,vpUnwsJejGkurJ,ISjplKfjrYLE,jZgXFIcRDQQkcI,XfKGtVsclDH,UtKeOSPhbf,,AtWJyGatftYCiA,pzEJCjFA,beuwjh,OrrcIHW,SjuBT,xVNUQEjxyB,CTDOUCAxhx,YpCApsrXvk,Gp,Us,ALBNnNFhdbMYjpl,msB,XniwYCr,aMImLpFlzbz,p,guQBgEARv,NRwcXFoVyjuRi,QfLRUsEQq,WrzdF,QVb,oDTGOMYEVu,iAfcPl,wLkI,VON,,P,TPwCynToFkJI,gZzcqx,QrZNqo,p,WSfbj,ldxi,taws,meZ,g,icjnchZcQQIqrnQ,RQRmriLCPE,Lxnxu,AoC,XNbQ,GhQqR,GSHHsytQGKNLJGU,PBi,IjIszY,WfXyRMqGBkI,jL,loeFjtFErHKhPv,YHAubVlaujA,hNAbVNu,sLhChzeLLvYXR,DnL,hamyOyGAouk,cNOZnSPNhoFjAFq,RXOFzh,JkgdgUCEI,ZidLIxtn,KaMuBFTdvSSN,Owj,dSHiNUxjaGQcieG,rVSK,DwxWsgHgbeiIVoF,I,NsOEAk,Hqdv,Xeedwold,aVFPYNWIehmpgZ,gH,yl,GDesAPfYPtrkDEx,YZbPYzQBUaseUBi,FYSJAlciOmnK,DjRdbezjrAdQcX,FUNKjgklfnksvn,NMCfDtqFvcI,T,rpkwYAmR,nTAJTyiVPbFuv,qKdFCrPCEPRE,xATVXeqsAKRcYV,tHzCGeqnplni,cXGiZMgXct,souXHmYybMmbyhg,i,oDhWt,L,kwesSP,jyksdMdyne,TCyYt,wX,JiSsPdDajKirPgL,cc,qnCQz,TS,luVvIgALvyB,,eGpRJq,RKWwtfwHo,ISEH,SiRldWBiF,jyFuxIz,cVojag,FGWd,HF,xI,xOwUyr,iDDEDH,vyDxjfVus,zLvpx,ssrFvXDVo,kXEzRcW,opsKOmCLbFwSM,xHfeHRWwalx,n,KOrSY,CAOTgyQJm,wCuuuzwffVEY,ldmjKUum,EDQzj,czqFC,GYAKCxOiu,nAM,uNQnVaBCj,TvoVlpJWYI,SFlUDJ,XTuQjsZtpUhgWId,D,xEiowDk,PaBftY,,PNdZMqagJawiLKy,pUcrcOEKSP,RlDCo,,kcK,RJugqQIBYfhC,W,ov,PzfdKIR,OBIa,JYXxqRucy,UaTDgAkJfw,,ydlnbzoww,fQdyIegvIc,DlT,LSqWLh,ihm,sR,MInOCbVexl,NuwJxdxvkTXa,nlJrPpKDIf,iWOwycGEID,PQdoTHebXj,DROZTCRnma,cFAMtx,BkYpK,JitcTdIPlTMEfl,wOSBOJEnIOw,CeEItVPQEeIfFgZ,OiCeEuVRKJ,hjFaJxsTYRCgFYz,giSKHpCNXNk,RaNmFDao,htRSneNtuDta,HdRaC,vkIkWSGebQbpaT,kzyJVn,gMMGxfRjFskmoo,xtfUXOdrlUs,CoSIbIPfVfTXko,zVOXIJ,UGQIlWuRzDJAPsn,,sWXjt,dNkgPEgim,WVmBPZSTa,KJnedQffhg,e,XhgwuoHiR,rt,FYNI,Rk,ImHT,QXR,Ta,wvU,qhsGIux,yyrLPMQmKVkCp,SBYM,a,aCxwZKlj,,lcNXLvIEkjQTO,XjpXtlM,PhdrxqxDVWO,pCIQtTuwu,WAbZHWAEtzLJOql,XDETKm,KuF,PozCBInp,d,tWtj,QKjx,eFevbQsOtGGxJM,FZIvXPnOKDMDgdB,khe,YdnPTMxczkm,L,SREiJirL,irZJxq,vl,SYsHw,vKSe,ypvRthKFyTRs,IuAdRz,lGotaaKUU,hxMTxzrUFT,dFCbGN,WDTco,xXhedTTXbbDllWX,M,MrhdNyXzFxP,LjX,qRqvrGrNzC,E,nQ,gOWQSgeCwVIq,ASGxcPYYmTAVm,gbnOqDOicyz,h,gviqOP,oV,QjDOngDXFeYp,ojPwZPSodxzxbu,jcWTp,ERHZmFboGYVCQxP,ox,PsFrmpSe,GbhohxlLVcU,rKMLpQNsvH,UzMJMaK,GilkAEVQWzUA,PGCrmxvKB,jOEDmSM,arTAqyNOUtsWj,,,sQXstIGqFfJg,FYOsFdUYr,DwYhqnBlsGtfez,FcKkwqG,sqZFwfyPByL,RkB,tYVdRtbHpdTRPBf,kObsAtqgghqe,,awzrSqHxz,,aXarXMPnQJgqJyM,ldb,NOdwJ,gUYvxxVPCcrmDOd,dcNR,,uglxXybrDyaHCU,JYRLQC,SoolzzZaZ,OZXZiMSimJrH,iZQiZl,bIDq,OSd,UopfHT,f,v,ynUYQwMmKrH,MtF,Cn,ad
|
data/spec/fixtures/malformed.csv
DELETED
data/spec/fixtures/money.csv
DELETED
data/spec/fixtures/no_header.csv
DELETED
data/spec/fixtures/numeric.csv
DELETED
data/spec/fixtures/pets.csv
DELETED
data/spec/fixtures/quoted.csv
DELETED
data/spec/fixtures/separator.csv
DELETED
@@ -1,5 +0,0 @@
|
|
1
|
-
"Artist","Track","Album","Label","Year"
|
2
|
-
Кино,"Мама, мы все сошли с ума",Группа Крови,Moroz Records,1998
|
3
|
-
"Кино","Мама, мы все сошли с ума","Группа Крови","Moroz Records",1998
|
4
|
-
Rammstein,Frühling in Paris,Liebe ist für alle da,Vagrant,2009
|
5
|
-
"Rammstein","Frühling in Paris","Liebe ist für alle da","Vagrant",2009
|
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
fixture_path = 'spec/fixtures'
|
4
|
-
|
5
|
-
# this reads a binary database dump file, which is in structure like a CSV file
|
6
|
-
# but contains control characters delimiting the rows and columns, and also
|
7
|
-
# contains a comment section which is commented our by a leading # character
|
8
|
-
|
9
|
-
# same as binary_file_spec , but reading the file with strings as keys
|
10
|
-
|
11
|
-
describe 'be_able_to' do
|
12
|
-
it 'loads_binary_file_with_strings_as_keys' do
|
13
|
-
options = {:col_sep => "\cA", :row_sep => "\cB", :comment_regexp => /^#/, :strings_as_keys => true}
|
14
|
-
data = SmarterCSV.process("#{fixture_path}/binary.csv", options)
|
15
|
-
data.flatten.size.should == 8
|
16
|
-
data.each do |item|
|
17
|
-
# all keys should be strings
|
18
|
-
item.keys.each{|x| x.class.should be == String}
|
19
|
-
item['timestamp'].should == 1381388409
|
20
|
-
item['item_id'].class.should be == Fixnum
|
21
|
-
item['name'].size.should be > 0
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
fixture_path = 'spec/fixtures'
|
4
|
-
|
5
|
-
# this reads a binary database dump file, which is in structure like a CSV file
|
6
|
-
# but contains control characters delimiting the rows and columns, and also
|
7
|
-
# contains a comment section which is commented our by a leading # character
|
8
|
-
|
9
|
-
describe 'be_able_to' do
|
10
|
-
it 'loads_binary_file_with_comments' do
|
11
|
-
options = {:col_sep => "\cA", :row_sep => "\cB", :comment_regexp => /^#/}
|
12
|
-
data = SmarterCSV.process("#{fixture_path}/binary.csv", options)
|
13
|
-
data.flatten.size.should == 8
|
14
|
-
data.each do |item|
|
15
|
-
# all keys should be symbols
|
16
|
-
item.keys.each{|x| x.class.should be == Symbol}
|
17
|
-
item[:timestamp].should == 1381388409
|
18
|
-
item[:item_id].class.should be == Fixnum
|
19
|
-
item[:name].size.should be > 0
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|