1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
|
== Recipes for Generating \CSV
These recipes are specific code examples for specific \CSV generating tasks.
For other recipes, see {Recipes for CSV}[./recipes_rdoc.html].
All code snippets on this page assume that the following has been executed:
require 'csv'
=== Contents
- {Output Formats}[#label-Output+Formats]
- {Generating to a String}[#label-Generating+to+a+String]
- {Recipe: Generate to String with Headers}[#label-Recipe-3A+Generate+to+String+with+Headers]
- {Recipe: Generate to String Without Headers}[#label-Recipe-3A+Generate+to+String+Without+Headers]
- {Generating to a File}[#label-Generating+to+a+File]
- {Recipe: Generate to File with Headers}[#label-Recipe-3A+Generate+to+File+with+Headers]
- {Recipe: Generate to File Without Headers}[#label-Recipe-3A+Generate+to+File+Without+Headers]
- {Generating to IO an Stream}[#label-Generating+to+an+IO+Stream]
- {Recipe: Generate to IO Stream with Headers}[#label-Recipe-3A+Generate+to+IO+Stream+with+Headers]
- {Recipe: Generate to IO Stream Without Headers}[#label-Recipe-3A+Generate+to+IO+Stream+Without+Headers]
- {Converting Fields}[#label-Converting+Fields]
- {Recipe: Filter Generated Field Strings}[#label-Recipe-3A+Filter+Generated+Field+Strings]
- {Recipe: Specify Multiple Write Converters}[#label-Recipe-3A+Specify+Multiple+Write+Converters]
- {RFC 4180 Compliance}[#label-RFC+4180+Compliance]
- {Row Separator}[#label-Row+Separator]
- {Recipe: Generate Compliant Row Separator}[#label-Recipe-3A+Generate+Compliant+Row+Separator]
- {Recipe: Generate Non-Compliant Row Separator}[#label-Recipe-3A+Generate+Non-Compliant+Row+Separator]
- {Column Separator}[#label-Column+Separator]
- {Recipe: Generate Compliant Column Separator}[#label-Recipe-3A+Generate+Compliant+Column+Separator]
- {Recipe: Generate Non-Compliant Column Separator}[#label-Recipe-3A+Generate+Non-Compliant+Column+Separator]
- {Quotes}[#label-Quotes]
- {Recipe: Quote All Fields}[#label-Recipe-3A+Quote+All+Fields]
- {Recipe: Quote Empty Fields}[#label-Recipe-3A+Quote+Empty+Fields]
- {Recipe: Generate Compliant Quote Character}[#label-Recipe-3A+Generate+Compliant+Quote+Character]
- {Recipe: Generate Non-Compliant Quote Character}[#label-Recipe-3A+Generate+Non-Compliant+Quote+Character]
=== Output Formats
You can generate \CSV output to a \String, to a \File (via its path), or to an \IO stream.
==== Generating to a \String
You can generate \CSV output to a \String, with or without headers.
===== Recipe: Generate to \String with Headers
Use class method CSV.generate with option +headers+ to generate to a \String.
This example uses method CSV#<< to append the rows
that are to be generated:
output_string = CSV.generate('', headers: ['Name', 'Value'], write_headers: true) do |csv|
csv << ['Foo', 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
output_string # => "Name,Value\nFoo,0\nBar,1\nBaz,2\n"
===== Recipe: Generate to \String Without Headers
Use class method CSV.generate without option +headers+ to generate to a \String.
This example uses method CSV#<< to append the rows
that are to be generated:
output_string = CSV.generate do |csv|
csv << ['Foo', 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
output_string # => "Foo,0\nBar,1\nBaz,2\n"
==== Generating to a \File
You can generate /CSV data to a \File, with or without headers.
===== Recipe: Generate to \File with Headers
Use class method CSV.open with option +headers+ generate to a \File.
This example uses method CSV#<< to append the rows
that are to be generated:
path = 't.csv'
CSV.open(path, 'w', headers: ['Name', 'Value'], write_headers: true) do |csv|
csv << ['Foo', 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
p File.read(path) # => "Name,Value\nFoo,0\nBar,1\nBaz,2\n"
===== Recipe: Generate to \File Without Headers
Use class method CSV.open without option +headers+ to generate to a \File.
This example uses method CSV#<< to append the rows
that are to be generated:
path = 't.csv'
CSV.open(path, 'w') do |csv|
csv << ['Foo', 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
p File.read(path) # => "Foo,0\nBar,1\nBaz,2\n"
==== Generating to an \IO Stream
You can generate \CSV data to an \IO stream, with or without headers.
==== Recipe: Generate to \IO Stream with Headers
Use class method CSV.new with option +headers+ to generate \CSV data to an \IO stream:
path = 't.csv'
File.open(path, 'w') do |file|
csv = CSV.new(file, headers: ['Name', 'Value'], write_headers: true)
csv << ['Foo', 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
p File.read(path) # => "Name,Value\nFoo,0\nBar,1\nBaz,2\n"
===== Recipe: Generate to \IO Stream Without Headers
Use class method CSV.new without option +headers+ to generate \CSV data to an \IO stream:
path = 't.csv'
File.open(path, 'w') do |file|
csv = CSV.new(file)
csv << ['Foo', 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
p File.read(path) # => "Foo,0\nBar,1\nBaz,2\n"
=== Converting Fields
You can use _write_ _converters_ to convert fields when generating \CSV.
==== Recipe: Filter Generated Field Strings
Use option <tt>:write_converters</tt> and a custom converter to convert field values when generating \CSV.
This example defines and uses a custom write converter to strip whitespace from generated fields:
strip_converter = proc {|field| field.respond_to?(:strip) ? field.strip : field }
output_string = CSV.generate(write_converters: strip_converter) do |csv|
csv << [' foo ', 0]
csv << [' bar ', 1]
csv << [' baz ', 2]
end
output_string # => "foo,0\nbar,1\nbaz,2\n"
==== Recipe: Specify Multiple Write Converters
Use option <tt>:write_converters</tt> and multiple custom converters
to convert field values when generating \CSV.
This example defines and uses two custom write converters to strip and upcase generated fields:
strip_converter = proc {|field| field.respond_to?(:strip) ? field.strip : field }
upcase_converter = proc {|field| field.respond_to?(:upcase) ? field.upcase : field }
converters = [strip_converter, upcase_converter]
output_string = CSV.generate(write_converters: converters) do |csv|
csv << [' foo ', 0]
csv << [' bar ', 1]
csv << [' baz ', 2]
end
output_string # => "FOO,0\nBAR,1\nBAZ,2\n"
=== RFC 4180 Compliance
By default, \CSV generates data that is compliant with
{RFC 4180}[https://www.rfc-editor.org/rfc/rfc4180]
with respect to:
- Column separator.
- Quote character.
==== Row Separator
RFC 4180 specifies the row separator CRLF (Ruby <tt>"\r\n"</tt>).
===== Recipe: Generate Compliant Row Separator
For strict compliance, use option +:row_sep+ to specify row separator <tt>"\r\n"</tt>:
output_string = CSV.generate('', row_sep: "\r\n") do |csv|
csv << ['Foo', 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
output_string # => "Foo,0\r\nBar,1\r\nBaz,2\r\n"
===== Recipe: Generate Non-Compliant Row Separator
For data with non-compliant row separators, use option +:row_sep+ with a different value:
This example source uses semicolon (<tt>";'</tt>) as its row separator:
output_string = CSV.generate('', row_sep: ";") do |csv|
csv << ['Foo', 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
output_string # => "Foo,0;Bar,1;Baz,2;"
==== Column Separator
RFC 4180 specifies column separator COMMA (Ruby <tt>","</tt>).
===== Recipe: Generate Compliant Column Separator
Because the \CSV default comma separator is <tt>","</tt>,
you need not specify option +:col_sep+ for compliant data:
output_string = CSV.generate('') do |csv|
csv << ['Foo', 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
output_string # => "Foo,0\nBar,1\nBaz,2\n"
===== Recipe: Generate Non-Compliant Column Separator
For data with non-compliant column separators, use option +:col_sep+.
This example source uses TAB (<tt>"\t"</tt>) as its column separator:
output_string = CSV.generate('', col_sep: "\t") do |csv|
csv << ['Foo', 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
output_string # => "Foo\t0\nBar\t1\nBaz\t2\n"
==== Quotes
IFC 4180 allows most fields to be quoted or not.
By default, \CSV does not quote most fields.
However, a field containing the current row separator, column separator,
or quote character is automatically quoted, producing IFC 4180 compliance:
# Field contains row separator.
output_string = CSV.generate('') do |csv|
row_sep = csv.row_sep
csv << ["Foo#{row_sep}Foo", 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
output_string # => "\"Foo\nFoo\",0\nBar,1\nBaz,2\n"
# Field contains column separator.
output_string = CSV.generate('') do |csv|
col_sep = csv.col_sep
csv << ["Foo#{col_sep}Foo", 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
output_string # => "\"Foo,Foo\",0\nBar,1\nBaz,2\n"
# Field contains quote character.
output_string = CSV.generate('') do |csv|
quote_char = csv.quote_char
csv << ["Foo#{quote_char}Foo", 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
output_string # => "\"Foo\"\"Foo\",0\nBar,1\nBaz,2\n"
===== Recipe: Quote All Fields
Use option +:force_quotes+ to force quoted fields:
output_string = CSV.generate('', force_quotes: true) do |csv|
csv << ['Foo', 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
output_string # => "\"Foo\",\"0\"\n\"Bar\",\"1\"\n\"Baz\",\"2\"\n"
===== Recipe: Quote Empty Fields
Use option +:quote_empty+ to force quoting for empty fields:
output_string = CSV.generate('', quote_empty: true) do |csv|
csv << ['Foo', 0]
csv << ['Bar', 1]
csv << ['', 2]
end
output_string # => "Foo,0\nBar,1\n\"\",2\n"
===== Recipe: Generate Compliant Quote Character
RFC 4180 specifies quote character DQUOTE (Ruby <tt>"\""</tt>).
Because the \CSV default quote character is also <tt>"\""</tt>,
you need not specify option +:quote_char+ for compliant data:
output_string = CSV.generate('', force_quotes: true) do |csv|
csv << ['Foo', 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
output_string # => "\"Foo\",\"0\"\n\"Bar\",\"1\"\n\"Baz\",\"2\"\n"
===== Recipe: Generate Non-Compliant Quote Character
For data with non-compliant quote characters, use option +:quote_char+.
This example source uses SQUOTE (<tt>"'"</tt>) as its quote character:
output_string = CSV.generate('', quote_char: "'", force_quotes: true) do |csv|
csv << ['Foo', 0]
csv << ['Bar', 1]
csv << ['Baz', 2]
end
output_string # => "'Foo','0'\n'Bar','1'\n'Baz','2'\n"
|