summaryrefslogtreecommitdiff
path: root/lib/csv.rb
diff options
context:
space:
mode:
authornahi <nahi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-05-26 14:30:30 +0000
committernahi <nahi@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-05-26 14:30:30 +0000
commit6dee0fab9b72b9c185fa742685f6486de9373243 (patch)
tree78cc93611ad0e5cc9dee981f60b647d10398064e /lib/csv.rb
parent74ab20eb3756f0061c89c2acda5ac972bd9cf69e (diff)
* lib/csv.rb (CSV.read, CSV.readlines): added. works as IO.read and
IO.readlines in CSV format. * lib/csv.rb (CSV.parse): [CAUTION] behavior changed. in the past, CSV.parse accepts a filename to be read-opened (it was just a shortcut of CSV.open(filename, 'r')). now CSV.parse accepts a string or a stream to be parsed e.g. CSV.parse("1,2\n3,r") #=> [['1', '2'], ['3', '4']] * test/csv/test_csv.rb: follow above changes. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@6410 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/csv.rb')
-rw-r--r--lib/csv.rb145
1 files changed, 82 insertions, 63 deletions
diff --git a/lib/csv.rb b/lib/csv.rb
index 26fc6435eb..0f6907be57 100644
--- a/lib/csv.rb
+++ b/lib/csv.rb
@@ -11,24 +11,17 @@
class CSV
class IllegalFormatError < RuntimeError; end
- def CSV.open(path, mode, fs = nil, rs = nil, &block)
- if mode == 'r' or mode == 'rb'
- open_reader(path, mode, fs, rs, &block)
- elsif mode == 'w' or mode == 'wb'
- open_writer(path, mode, fs, rs, &block)
- else
- raise ArgumentError.new("'mode' must be 'r', 'rb', 'w', or 'wb'")
- end
- end
-
- def CSV.foreach(path, rs = nil, &block)
- open_reader(path, 'r', ',', rs, &block)
- end
-
- # Open a CSV formatted file for reading.
+ # Open a CSV formatted file for reading or writing.
+ #
+ # For reading.
#
# EXAMPLE 1
- # reader = CSV.parse('csvfile.csv')
+ # CSV.open('csvfile.csv', 'r') do |row|
+ # p row
+ # end
+ #
+ # EXAMPLE 2
+ # reader = CSV.open('csvfile.csv', 'r')
# row1 = reader.shift
# row2 = reader.shift
# if row2.empty?
@@ -36,11 +29,6 @@ class CSV
# end
# reader.close
#
- # EXAMPLE 2
- # CSV.parse('csvfile.csv') do |row|
- # p row
- # end
- #
# ARGS
# filename: filename to parse.
# col_sep: Column separator. ?, by default. If you want to separate
@@ -51,24 +39,21 @@ class CSV
# RETURNS
# reader instance. To get parse result, see CSV::Reader#each.
#
- def CSV.parse(path, fs = nil, rs = nil, &block)
- open_reader(path, 'r', fs, rs, &block)
- end
-
- # Open a CSV formatted file for writing.
#
- # EXAMPLE 1
- # writer = CSV.generate('csvfile.csv')
- # writer << ['r1c1', 'r1c2'] << ['r2c1', 'r2c2'] << [nil, nil]
- # writer.close
+ # For writing.
#
- # EXAMPLE 2
- # CSV.generate('csvfile.csv') do |writer|
+ # EXAMPLE 1
+ # CSV.open('csvfile.csv', 'w') do |writer|
# writer << ['r1c1', 'r1c2']
# writer << ['r2c1', 'r2c2']
# writer << [nil, nil]
# end
#
+ # EXAMPLE 2
+ # writer = CSV.open('csvfile.csv', 'w')
+ # writer << ['r1c1', 'r1c2'] << ['r2c1', 'r2c2'] << [nil, nil]
+ # writer.close
+ #
# ARGS
# filename: filename to generate.
# col_sep: Column separator. ?, by default. If you want to separate
@@ -80,10 +65,49 @@ class CSV
# writer instance. See CSV::Writer#<< and CSV::Writer#add_row to know how
# to generate CSV string.
#
+ def CSV.open(path, mode, fs = nil, rs = nil, &block)
+ if mode == 'r' or mode == 'rb'
+ open_reader(path, mode, fs, rs, &block)
+ elsif mode == 'w' or mode == 'wb'
+ open_writer(path, mode, fs, rs, &block)
+ else
+ raise ArgumentError.new("'mode' must be 'r', 'rb', 'w', or 'wb'")
+ end
+ end
+
+ def CSV.foreach(path, rs = nil, &block)
+ open_reader(path, 'r', ',', rs, &block)
+ end
+
+ def CSV.read(path, length = nil, offset = nil)
+ CSV.parse(IO.read(path, length, offset))
+ end
+
+ def CSV.readlines(path, rs = nil)
+ reader = open_reader(path, 'r', ',', rs)
+ begin
+ reader.collect { |row| row }
+ ensure
+ reader.close
+ end
+ end
+
def CSV.generate(path, fs = nil, rs = nil, &block)
open_writer(path, 'w', fs, rs, &block)
end
+ # Parse lines from given string or stream. Return rows as an Array of Arrays.
+ def CSV.parse(str_or_readable, fs = nil, rs = nil, &block)
+ if block
+ CSV::Reader.parse(str_or_readable, fs, rs) do |row|
+ yield(row)
+ end
+ nil
+ else
+ CSV::Reader.create(str_or_readable, fs, rs).collect { |row| row }
+ end
+ end
+
# Parse a line from given string. Bear in mind it parses ONE LINE. Rest of
# the string is ignored for example "a,b\r\nc,d" => ['a', 'b'] and the
# second line 'c,d' is ignored.
@@ -157,7 +181,7 @@ class CSV
# src[](idx_out_of_bounds) must return nil. A String satisfies this
# requirement.
# idx: index of parsing location of 'src'. 0 origin.
- # out_dev: buffer for parsed cells. Must respond '<<(CSV::Cell)'.
+ # out_dev: buffer for parsed cells. Must respond '<<(aString)'.
# col_sep: Column separator. ?, by default. If you want to separate
# fields with semicolon, give ?; here.
# row_sep: Row separator. nil by default. nil means "\r\n or \n". If you
@@ -200,13 +224,9 @@ class CSV
# instead. To generate multi-row CSV string, see EXAMPLE below.
#
# EXAMPLE
- # def d(str)
- # CSV::Cell.new(str, false)
- # end
- #
- # row1 = [d('a'), d('b')]
- # row2 = [d('c'), d('d')]
- # row3 = [d('e'), d('f')]
+ # row1 = ['a', 'b']
+ # row2 = ['c', 'd']
+ # row3 = ['e', 'f']
# src = [row1, row2, row3]
# buf = ''
# src.each do |row|
@@ -216,8 +236,8 @@ class CSV
# p buf
#
# ARGS
- # src: an Array of CSV::Cell to be converted to CSV string. Must respond to
- # 'size' and '[](idx)'. src[idx] must return CSV::Cell.
+ # src: an Array of String to be converted to CSV string. Must respond to
+ # 'size' and '[](idx)'. src[idx] must return String.
# cells: num of cells in a line.
# out_dev: buffer for generated CSV string. Must respond to '<<(string)'.
# col_sep: Column separator. ?, by default. If you want to separate
@@ -485,13 +505,17 @@ class CSV
# Parse CSV data and get lines. Given block is called for each parsed row.
# Block value is always nil. Rows are not cached for performance reason.
- def Reader.parse(str_or_readable, fs = ',', rs = nil)
- reader = create(str_or_readable, fs, rs)
- reader.each do |row|
- yield(row)
+ def Reader.parse(str_or_readable, fs = ',', rs = nil, &block)
+ reader = Reader.create(str_or_readable, fs, rs)
+ if block
+ reader.each do |row|
+ yield(row)
+ end
+ reader.close
+ nil
+ else
+ reader
end
- reader.close
- nil
end
# Returns reader instance.
@@ -619,28 +643,23 @@ class CSV
# outfile = File.open('csvout', 'wb')
# CSV::Writer.generate(outfile) do |csv|
# csv << ['c1', nil, '', '"', "\r\n", 'c2']
- # # or
- # csv.add_row [
- # CSV::Cell.new('c1', false),
- # CSV::Cell.new('dummy', true),
- # CSV::Cell.new('', false),
- # CSV::Cell.new('"', false),
- # CSV::Cell.new("\r\n", false)
- # CSV::Cell.new('c2', false)
- # ]
- # ...
# ...
# end
#
# outfile.close
#
class Writer
- # Generate CSV. Given block is called with the writer instance.
- def Writer.generate(str_or_writable, fs = ',', rs = nil)
+ # Given block is called with the writer instance. str_or_writable must
+ # handle '<<(string)'.
+ def Writer.generate(str_or_writable, fs = ',', rs = nil, &block)
writer = Writer.create(str_or_writable, fs, rs)
- yield(writer)
- writer.close
- nil
+ if block
+ yield(writer)
+ writer.close
+ nil
+ else
+ writer
+ end
end
# str_or_writable must handle '<<(string)'.