You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A `CSVReadder` parses CSV data from a given input (`String`, or `Data`, or file) and returns CSV rows as a `String`s array. `CSVReader` can be used at a "high-level", in which case it parses an input completely; or at a lower level, in which each row is decoded when requested.
70
+
A `CSVReadder` parses CSV data from a given input (`String`, or `Data`, or file) and returns CSV rows as a `String`s array. `CSVReader` can be used at a _high-level_, in which case it parses an input completely; or at a _low-level_, in which each row is decoded when requested.
40
71
41
72
- Complete input parsing.
42
73
43
74
```swift
44
-
let file =try CSVReader.parse(input: ...)
45
-
// file is of type: CSVReader.Output
75
+
let data: Data =...
76
+
let result =try CSVReader.parse(input: data)
77
+
78
+
// `result` lets you access the CSV headers, all CSV rows, or access a specific row/record. For example:
79
+
let headers = result.headers// [String]
80
+
let content = result.rows// [[String]]
81
+
let fieldA = result[row: 2, field: "Age"] // String? (crash if the row index are out of bounds)
82
+
let fieldB = result[row: 3, field: 2] // String (crash if the row or field index are out of bounds)
46
83
```
47
84
48
-
This type of parsing returns a simple structure containing the CSV headers and CSV rows. Additionally it lets you access each field through the header name or the field index.
49
-
50
85
- Row-by-row parsing.
51
86
52
87
```swift
53
-
let reader =tryCSVReader(input: "...")
54
-
whilelet row =try reader.parseRow() {
55
-
// Do something with the row: [String]
56
-
}
88
+
let string ="""
89
+
numA,numB,numC
90
+
1,2,3
91
+
4,5,6
92
+
"""
93
+
let reader =tryCSVReader(input: string) { $0.headerStrategy= .firstLine }
94
+
95
+
let headers = reader.headers// ["numA", "numB", "numC"]
96
+
let rowA =try reader.parseRow() // ["1", "2", "3"]
97
+
let rowB =try reader.parseRow() // ["4", "5", "6"]
57
98
```
58
99
59
100
Alternatively you can use the `parseRecord()` function which also returns the next CSV row, but it wraps the result in a convenience structure. This structure lets you access each field with the header name (as long as the `headerStrategy` is marked with `.firstLine`).
60
101
102
+
```swift
103
+
let reader =tryCSVReader(input: string) { $0.headerStrategy= .firstLine }
104
+
105
+
let headers = reader.headers// ["numA", "numB", "numC"]
106
+
107
+
let recordA =try reader.parseRecord()
108
+
let rowA = recordA.row// ["1", "2", "3"]
109
+
let firstField = recordA[0] // "1"
110
+
let secondField = recordA["numB"] // "2"
111
+
112
+
let recordB =try reader.parseRecord()
113
+
```
114
+
61
115
- `Sequence` syntax parsing.
62
116
63
117
```swift
@@ -108,32 +162,95 @@ let reader = CSVReader(input: ...) {
A `CSVWriter` encodes CSV information into a specified target (i.e. a `String`, or `Data`, or a file). It can be used at a "high-level", by encoding completely a prepared setof information; or at a lower level, in which case rows or fields can be writen individually.
165
+
A `CSVWriter` encodes CSV information into a specified target (i.e. a `String`, or `Data`, or a file). It can be used at a _high-level_, by encoding completely a prepared setof information; or at a _low-level_, in which case rows or fields can be writen individually.
112
166
113
-
-Full encoding.
167
+
-Complete CSV rows serialization.
114
168
115
169
```swift
116
-
let data =try CSVWriter.serialize(rows: [...], into: Data.self)
170
+
let input = [
171
+
["numA", "numB", "name" ],
172
+
["1" , "2" , "Marcos" ],
173
+
["4" , "5" , "Marine-Anaïs"]
174
+
]
175
+
let data =try CSVWriter.serialize(rows: input, into: Data.self)
176
+
let string =try CSVWriter.serialize(rows: input, into: String.self)
177
+
let file =try CSVWriter.serialize(rows: input, into: URL("~/Desktop/Test.csv")!, append: false)
117
178
```
118
179
119
180
- Row-by-row encoding.
120
181
121
182
```swift
122
-
let writer =tryCSVWriter()
123
-
for row in customData {
183
+
let writer =tryCSVWriter(fileURL: URL("~/Desktop/Test.csv")!, append: false)
184
+
for row in input {
185
+
try writer.write(row: row)
186
+
}
187
+
try writer.endFile()
188
+
```
189
+
190
+
Alternatively, you may write directly to a buffer in memory and access its `Data` representation.
191
+
192
+
```swift
193
+
let writer =tryCSVWriter { $0.headers= input[0] }
194
+
for row in input.dropFirst() {
124
195
try writer.write(row: row)
125
196
}
126
-
let outcome = writer.data()
197
+
try writer.endFile()
198
+
let result =try writer.data()
127
199
```
128
200
129
201
- Field-by-field encoding.
130
202
131
203
```swift
132
-
let writer =tryCSVWriter(fileURL: ...)
133
-
try writer.write(field: ...)
204
+
let writer =tryCSVWriter(fileURL: URL("~/Desktop/Test.csv")!, append: false)
205
+
try writer.write(row: input[0])
206
+
207
+
input[1].forEach {
208
+
try writer.write(field: field)
209
+
}
210
+
try writer.endRow()
211
+
212
+
try writer.write(fields: input[2])
213
+
try writer.endRow()
214
+
215
+
try writer.endFile()
134
216
```
135
217
136
-
#warning("TODO:")
218
+
`CSVWriter` has a wealth of low-level imperative APIs, that let you write one field, several fields at a time, end a row, write an empty row, etc.
219
+
220
+
> Please notice that a CSV requires all rows to have the same amount of fields.
221
+
222
+
`CSVWriter` enforces this by throwing an error when you try to write more the expected amount of fields, or filling a row with empty fields when you call `endRow()` but not all fields has been written.
223
+
224
+
### Writer Configuration
225
+
226
+
`CSVWriter` accepts the following configuration properties:
227
+
228
+
-`delimiters` (default: `(field: ",", row: "\n")`) specify the field and row delimiters.
229
+
230
+
CSV fields are separated within a row with _field delimiters_ (commonly a "comma"). CSV rows are separated through _row delimiters_ (commonly a "line feed"). You can specify any unicode scalar, `String` value, or `nil` for unknown delimiters.
231
+
232
+
-`headers` (default: `[]`) indicates whether the CSV data has a header row or not.
233
+
234
+
CSV files may contain an optional header row at the very beginning. If this configuration value is empty, no header row is writen.
235
+
236
+
-`encoding` (default: `nil`) specify the CSV file encoding.
237
+
238
+
This `String.Encoding` value specify how each underlying byte isrepresented (e.g. `.utf8`, `.utf32littleEndian`, etc.). If it is `nil`, the library will try to figure out the file encoding through the file's [Byte Order Marker](https://en.wikipedia.org/wiki/Byte_order_mark). If the file doesn't contain a BOM, `.utf8` is presumed.
239
+
240
+
-`bomStrategy` (default: `.convention`) indicates whether a Byte Order Marker will be included at the beginning of the CSV representation.
241
+
242
+
The OS convention is that BOMs are never writen, except when `.utf16`, `.utf32`, or `.unicode` string encodings are specified. You could however indicate that you always want the BOM writen (`.always`) or that is never writer (`.never`).
243
+
244
+
The configuration values are set during initialization and can be passed to the `CSWriter` instance through a structure or with a convenience closure syntax:
0 commit comments