-
Notifications
You must be signed in to change notification settings - Fork 265
Expand file tree
/
Copy pathCSVExporter.swift
More file actions
77 lines (57 loc) · 1.94 KB
/
CSVExporter.swift
File metadata and controls
77 lines (57 loc) · 1.94 KB
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
//
// CSVExporter.swift
// BuildTimeAnalyzer
//
// Created by Bruno Resende on 16.01.19.
// Copyright © 2019 Cane Media Ltd. All rights reserved.
//
import Foundation
struct CSVExporter {
static var filenameDateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyyMMdd-HHmmss"
return formatter
}()
func filename(with prefix: String) -> String {
return "\(prefix)_\(CSVExporter.filenameDateFormatter.string(from: Date())).csv"
}
func export<T>(elements: [T], to url: URL) throws where T: CSVExportable {
guard let data = elements.joinedAsCSVString(delimiter: .doubleQuote).data(using: .utf8) else {
throw ExportErrors.couldNotParseStringAsUTF8
}
do {
try data.write(to: url, options: .atomic)
} catch {
throw ExportErrors.fileIO(error)
}
}
enum ExportErrors: Error {
case couldNotParseStringAsUTF8
case fileIO(Error)
}
}
enum CSVDelimiter: String {
case singleQuote = "'"
case doubleQuote = "\""
case none = ""
}
protocol CSVExportable {
static var csvHeaderLine: String { get }
var csvLine: String { get }
}
extension Array where Element: CSVExportable {
func joinedAsCSVString(delimiter: CSVDelimiter) -> String {
return ([Element.csvHeaderLine] + self.map({ $0.csvLine })).joined(separator: "\n")
}
}
extension Array where Element == String {
func joinedAsCSVLine(delimiter: CSVDelimiter) -> String {
let formatter: (String) -> String
switch delimiter {
case .singleQuote: formatter = { $0.replacingOccurrences(of: "'", with: "\\'") }
case .doubleQuote: formatter = { $0.replacingOccurrences(of: "\"", with: "\\\"") }
case .none: formatter = { $0 }
}
return self.map({ "\(delimiter.rawValue)\(formatter($0))\(delimiter.rawValue)" }).joined(separator: ",")
}
}