lightcsv 0.2.3 → 0.2.4
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 +36 -0
- data/lib/lightcsv.rb +41 -62
- metadata +2 -2
- data/README.txt +0 -72
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
LightCsv
|
2
|
+
========
|
3
|
+
|
4
|
+
Description
|
5
|
+
-----------
|
6
|
+
|
7
|
+
LightCsv is CSV paresr.
|
8
|
+
|
9
|
+
Installation
|
10
|
+
------------
|
11
|
+
|
12
|
+
% gem install lightcsv
|
13
|
+
|
14
|
+
Differ from csv.rb
|
15
|
+
------------------
|
16
|
+
|
17
|
+
* CSV record separator is LF, CR or CR LF.
|
18
|
+
* LightCsv never returns nil. The empty column is "".
|
19
|
+
|
20
|
+
Examples
|
21
|
+
--------
|
22
|
+
|
23
|
+
LightCsv.foreach(filename){|row| ...}
|
24
|
+
LightCsv.readlines(filename) #=> [[col1, col2, ...], ...]
|
25
|
+
LightCsv.parse(string){|row| ...}
|
26
|
+
LightCsv.parse(string) #=> [col1, col2, ...], ...]
|
27
|
+
|
28
|
+
Copyright
|
29
|
+
---------
|
30
|
+
|
31
|
+
Copyright (c) 2007 TOMITA Masahiro <tommy@tmtm.org>
|
32
|
+
|
33
|
+
License
|
34
|
+
-------
|
35
|
+
|
36
|
+
Ruby's license <http://www.ruby-lang.org/en/about/license.txt>
|
data/lib/lightcsv.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# coding: us-ascii
|
2
2
|
# = LightCsv
|
3
3
|
# CSV parser
|
4
4
|
#
|
@@ -8,60 +8,35 @@
|
|
8
8
|
|
9
9
|
require "strscan"
|
10
10
|
|
11
|
-
#
|
12
|
-
# 各レコードはカラムを要素とする配列である。
|
13
|
-
# レコードの区切りは LF,CR,CRLF のいずれか。
|
14
|
-
#
|
15
|
-
# 以下が csv.rb と異なる。
|
16
|
-
# * 空行は [nil] ではなく [] になる。
|
17
|
-
# * 「"」で括られていない空カラムは nil ではなく "" になる。
|
18
|
-
#
|
19
|
-
# == 例
|
20
|
-
# * CSVファイルのレコード毎にブロックを繰り返す。
|
21
|
-
# LightCsv.foreach(filename){|row| ...}
|
22
|
-
# 次と同じ。
|
23
|
-
# LightCsv.open(filename){|csv| csv.each{|row| ...}}
|
24
|
-
#
|
25
|
-
# * CSVファイルの全レコードを返す。
|
26
|
-
# LightCsv.readlines(filename) # => [[col1,col2,...],...]
|
27
|
-
# 次と同じ。
|
28
|
-
# LightCsv.open(filename){|csv| csv.entries}
|
29
|
-
#
|
30
|
-
# * CSV文字列のレコード毎にブロックを繰り返す。
|
31
|
-
# LightCsv.parse("a1,a2,..."){|row| ...}
|
32
|
-
# 次と同じ。
|
33
|
-
# LightCsv.new("a1,a2,...").each{|row| ...}
|
34
|
-
#
|
35
|
-
# * CSV文字列の全レコードを返す。
|
36
|
-
# LightCsv.parse("a1,a2,...") # => [[a1,a2,...],...]
|
37
|
-
# 次と同じ。
|
38
|
-
# LightCsv.new("a1,a2,...").entries
|
39
|
-
#
|
11
|
+
# CSV parser
|
40
12
|
class LightCsv
|
41
13
|
include Enumerable
|
42
14
|
|
43
|
-
# == パースできない形式の場合に発生する例外
|
44
|
-
# InvalidFormat#message は処理できなかった位置から 10バイト分の文字列を返す。
|
45
15
|
class InvalidFormat < RuntimeError; end
|
46
16
|
|
47
|
-
#
|
48
|
-
#
|
17
|
+
# @param [String] filename Filename
|
18
|
+
# @yield [row]
|
19
|
+
# @yieldparam [Array<String>] row One record
|
20
|
+
# @return [void]
|
49
21
|
def self.foreach(filename, &block)
|
50
22
|
self.open(filename) do |f|
|
51
23
|
f.each(&block)
|
52
24
|
end
|
53
25
|
end
|
54
26
|
|
55
|
-
#
|
27
|
+
# @param [String] filename Filename
|
28
|
+
# @return [Array<Array<String>>] All records.
|
56
29
|
def self.readlines(filename)
|
57
30
|
self.open(filename) do |f|
|
58
31
|
return f.entries
|
59
32
|
end
|
60
33
|
end
|
61
34
|
|
62
|
-
# CSV
|
63
|
-
#
|
64
|
-
#
|
35
|
+
# @param [String] string CSV string
|
36
|
+
# @yield [row]
|
37
|
+
# @yieldparam [Array<String>] row One record
|
38
|
+
# @return [Array<Array<String>>] if block is unspecified
|
39
|
+
# @return [nil] if block is specified
|
65
40
|
def self.parse(string, &block)
|
66
41
|
unless block
|
67
42
|
return self.new(string).entries
|
@@ -72,8 +47,11 @@ class LightCsv
|
|
72
47
|
return nil
|
73
48
|
end
|
74
49
|
|
75
|
-
#
|
76
|
-
#
|
50
|
+
# @param [String] filename Filename
|
51
|
+
# @yield [csv]
|
52
|
+
# @yieldparam [LightCsv] csv LightCsv object
|
53
|
+
# @return [LightCsv] if block is unspecified
|
54
|
+
# @return [Object] block value if block is specified
|
77
55
|
def self.open(filename, &block)
|
78
56
|
f = File.open(filename)
|
79
57
|
csv = self.new(f)
|
@@ -88,8 +66,7 @@ class LightCsv
|
|
88
66
|
end
|
89
67
|
end
|
90
68
|
|
91
|
-
#
|
92
|
-
# _src_ は String か IO。
|
69
|
+
# @param [String / IO] src CSV source
|
93
70
|
def initialize(src)
|
94
71
|
if src.kind_of? String
|
95
72
|
@file = nil
|
@@ -103,15 +80,16 @@ class LightCsv
|
|
103
80
|
end
|
104
81
|
attr_accessor :bufsize
|
105
82
|
|
106
|
-
#
|
107
|
-
|
83
|
+
# close file
|
84
|
+
# @return [void]
|
85
|
+
def close
|
108
86
|
@file.close if @file
|
109
87
|
end
|
110
88
|
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
def shift
|
89
|
+
# return one record.
|
90
|
+
# @return [Array<String>] one record. empty array for empty line.
|
91
|
+
# @return [nil] if end of data is reached.
|
92
|
+
def shift
|
115
93
|
return nil if @ss.eos? and ! read_next_data
|
116
94
|
cols = []
|
117
95
|
while true
|
@@ -119,13 +97,13 @@ class LightCsv
|
|
119
97
|
cols << ""
|
120
98
|
break
|
121
99
|
end
|
122
|
-
if @ss.scan(/\"/
|
123
|
-
until @ss.scan(/((?:\"\"|[^\"])*)\"(,|\r\n|\n|\r|\z)/
|
100
|
+
if @ss.scan(/\"/)
|
101
|
+
until @ss.scan(/((?:\"\"|[^\"])*)\"(,|\r\n|\n|\r|\z)/)
|
124
102
|
read_next_data or raise InvalidFormat, @ss.rest[0,10]
|
125
103
|
end
|
126
|
-
cols << @ss[1].gsub(/\"\"
|
104
|
+
cols << @ss[1].gsub(/\"\"/, '"')
|
127
105
|
else
|
128
|
-
unless @ss.scan(/([^\",\r\n]*)(,|\r\n|\n|\r|\z)/
|
106
|
+
unless @ss.scan(/([^\",\r\n]*)(,|\r\n|\n|\r|\z)/)
|
129
107
|
raise InvalidFormat, @ss.rest[0,10]
|
130
108
|
end
|
131
109
|
cols << @ss[1]
|
@@ -136,30 +114,31 @@ class LightCsv
|
|
136
114
|
cols
|
137
115
|
end
|
138
116
|
|
139
|
-
#
|
140
|
-
|
117
|
+
# iterator
|
118
|
+
# @yield [row]
|
119
|
+
# @yieldparam [Array<String>] row One record
|
120
|
+
def each
|
141
121
|
while row = shift
|
142
122
|
yield row
|
143
123
|
end
|
144
124
|
end
|
145
125
|
|
146
|
-
#
|
147
|
-
|
126
|
+
# Array of record
|
127
|
+
# @return [Array<Array<String>>] records
|
128
|
+
def readlines
|
148
129
|
return entries
|
149
130
|
end
|
150
131
|
|
151
132
|
private
|
152
133
|
|
153
|
-
#
|
154
|
-
|
155
|
-
# ファイルの最後まで達した場合は nil を返す。
|
156
|
-
def read_next_data()
|
134
|
+
# @return [nil] when EOF reached.
|
135
|
+
def read_next_data
|
157
136
|
return unless @file && @buf
|
158
137
|
while buf = @file.read(@bufsize)
|
159
138
|
@buf.concat buf
|
160
|
-
if l = @buf.slice!(/\A.*(?:\r\n|\r(.)|\n)/
|
139
|
+
if l = @buf.slice!(/\A.*(?:\r\n|\r(.)|\n)/m)
|
161
140
|
if $1
|
162
|
-
@buf[0,0] = $1
|
141
|
+
@buf[0,0] = $1
|
163
142
|
l.chop!
|
164
143
|
end
|
165
144
|
@ss.string = @ss.rest + l
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lightcsv
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -17,7 +17,7 @@ executables: []
|
|
17
17
|
extensions: []
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
|
-
- README.
|
20
|
+
- README.md
|
21
21
|
- lib/lightcsv.rb
|
22
22
|
- test/test_lightcsv.rb
|
23
23
|
homepage: http://github.com/tmtm/lightcsv
|
data/README.txt
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
= LightCsv =
|
2
|
-
CSV パーサ
|
3
|
-
|
4
|
-
== 作者 ==
|
5
|
-
|
6
|
-
とみたまさひろ <tommy@tmtm.org>
|
7
|
-
|
8
|
-
== ライセンス ==
|
9
|
-
|
10
|
-
Ruby ライセンス http://www.ruby-lang.org/ja/LICENSE.txt と同等。
|
11
|
-
|
12
|
-
== 機能 ==
|
13
|
-
|
14
|
-
* CSV をパースして配列を返す。
|
15
|
-
|
16
|
-
== ダウンロード ==
|
17
|
-
|
18
|
-
* http://tmtm.org/downloads/ruby/lightcsv/
|
19
|
-
|
20
|
-
== インストール ==
|
21
|
-
|
22
|
-
{{{
|
23
|
-
$ make
|
24
|
-
$ make test
|
25
|
-
# make install
|
26
|
-
}}}
|
27
|
-
|
28
|
-
== CSVのパース ==
|
29
|
-
|
30
|
-
各レコードはカラムを要素とする配列である。
|
31
|
-
レコードの区切りは LF,CR,CRLF のいずれか。
|
32
|
-
|
33
|
-
以下が csv.rb と異なる。
|
34
|
-
* 空行は [nil] ではなく [] になる。
|
35
|
-
* 「"」で括られていない空カラムは nil ではなく "" になる。
|
36
|
-
|
37
|
-
== 使用例 ==
|
38
|
-
* CSVファイルのレコード毎にブロックを繰り返す。
|
39
|
-
{{{
|
40
|
-
LightCsv.foreach(filename){|row| ...}
|
41
|
-
}}}
|
42
|
-
次と同じ。
|
43
|
-
{{{
|
44
|
-
LightCsv.open(filename){|csv| csv.each{|row| ...}}
|
45
|
-
}}}
|
46
|
-
|
47
|
-
* CSVファイルの全レコードを返す。
|
48
|
-
{{{
|
49
|
-
LightCsv.readlines(filename) # => [[col1,col2,...],...]
|
50
|
-
}}}
|
51
|
-
次と同じ。
|
52
|
-
{{{
|
53
|
-
LightCsv.open(filename){|csv| csv.map}
|
54
|
-
}}}
|
55
|
-
|
56
|
-
* CSV文字列のレコード毎にブロックを繰り返す。
|
57
|
-
{{{
|
58
|
-
LightCsv.parse("a1,a2,..."){|row| ...}
|
59
|
-
}}}
|
60
|
-
次と同じ。
|
61
|
-
{{{
|
62
|
-
LightCsv.new("a1,a2,...").each{|row| ...}
|
63
|
-
}}}
|
64
|
-
|
65
|
-
* CSV文字列の全レコードを返す。
|
66
|
-
{{{
|
67
|
-
LightCsv.parse("a1,a2,...") # => [[a1,a2,...],...]
|
68
|
-
}}}
|
69
|
-
次と同じ。
|
70
|
-
{{{
|
71
|
-
LightCsv.new("a1,a2,...").map
|
72
|
-
}}}
|