### CSVReader Full Configuration Example Source: https://context7.com/dehesa/codablecsv/llms.txt Illustrates a comprehensive configuration for CSV reading, including encoding, delimiters, escaping, header handling, trimming, and presampling. ```swift import CodableCSV // Full configuration example var config = CSVReader.Configuration() // Encoding: nil means auto-detect from BOM, defaults to UTF-8 config.encoding = .utf8 // config.encoding = .utf16 // config.encoding = nil // Auto-detect // Delimiters: field and row separators config.delimiters = (field: ",", row: "\n") // Default (CSV) // config.delimiters = (field: "\t", row: "\n") // TSV (Tab-separated) // config.delimiters = (field: ";", row: "\r\n") // European CSV with Windows line endings // Escaping strategy: how fields with special characters are handled config.escapingStrategy = .doubleQuote // Default: use " to escape // config.escapingStrategy = .none // Disable escaping // Header strategy: whether first row contains headers config.headerStrategy = .none // No headers // config.headerStrategy = .firstLine // First row is headers // Trim strategy: characters to remove from field boundaries config.trimStrategy = .whitespaces // Trim spaces and tabs // config.trimStrategy = CharacterSet() // No trimming (default) // Presample: load entire file into memory before parsing config.presample = false // Default: stream from source // config.presample = true // Load all at once (faster for small files) // Using configuration let reader = try CSVReader(input: csvData, configuration: config) ``` -------------------------------- ### CSV Encoding to Data and File Source: https://context7.com/dehesa/codablecsv/llms.txt Encodes Swift types conforming to Encodable into CSV format. This example shows encoding to Data and directly to a file. ```swift import CodableCSV struct Product: Encodable { let sku: String let name: String let price: Decimal let inStock: Bool } let products = [ Product(sku: "A001", name: "Widget", price: 19.99, inStock: true), Product(sku: "A002", name: "Gadget", price: 29.99, inStock: false), Product(sku: "A003", name: "Gizmo", price: 39.99, inStock: true) ] let encoder = CSVEncoder { config.headers = ["sku", "name", "price", "inStock"] } // Encode to Data let csvData = try encoder.encode(products, into: Data.self) // Encode directly to file let fileURL = URL(fileURLWithPath: "/tmp/products.csv") try encoder.encode(products, into: fileURL) ``` -------------------------------- ### Read CSV Records with Header Access Source: https://github.com/dehesa/codablecsv/blob/master/README.md Use readRecord() to get a convenience structure for accessing fields by header name when headerStrategy is .firstLine. Each record provides direct access to its row and fields. ```swift let reader = try CSVReader(input: string) { $0.headerStrategy = .firstLine } let headers = reader.headers // ["numA", "numB", "numC"] let recordA = try reader.readRecord() let rowA = recordA.row // ["1", "2", "3"] let fieldA = recordA[0] // "1" let fieldB = recordA["numB"] // "2" let recordB = try reader.readRecord() ``` -------------------------------- ### Configure CSVEncoder options Source: https://context7.com/dehesa/codablecsv/llms.txt Demonstrates the various configuration strategies available for the CSVEncoder, such as nil handling, date formatting, and buffering. ```swift import CodableCSV let encoder = CSVEncoder { config in // Writer configuration (inherited) config.headers = ["id", "name", "created", "active"] config.encoding = .utf8 config.delimiters = (field: ",", row: "\n") config.bomStrategy = .never // Nil strategy: how nil values are written config.nilStrategy = .empty // Default: empty string // config.nilStrategy = .custom("NULL") // Boolean strategy config.boolStrategy = .deferredToString // Default: "true"/"false" // config.boolStrategy = .numeric // "1"/"0" // Non-conforming float strategy (NaN, Infinity) config.nonConformingFloatStrategy = .throw // Default // config.nonConformingFloatStrategy = .convert( // positiveInfinity: "Inf", // negativeInfinity: "-Inf", // nan: "NaN" // ) // Decimal strategy config.decimalStrategy = .locale(.current) // config.decimalStrategy = .custom { decimal, encoder in ... } // Date strategy config.dateStrategy = .deferredToDate // Default // config.dateStrategy = .iso8601 // config.dateStrategy = .secondsSince1970 // config.dateStrategy = .millisecondsSince1970 // config.dateStrategy = .formatted(myDateFormatter) // config.dateStrategy = .custom { date, encoder in ... } // Data strategy config.dataStrategy = .base64 // Default // config.dataStrategy = .custom { data, encoder in ... } // Buffering strategy config.bufferingStrategy = .keepAll // Default: buffer all rows // config.bufferingStrategy = .sequential // Write immediately (for lazy) // config.bufferingStrategy = .assembled // Assemble before writing } ``` ```swift // Encoding with ISO8601 dates and numeric booleans let isoEncoder = CSVEncoder { config in config.headers = ["timestamp", "enabled"] config.dateStrategy = .iso8601 config.boolStrategy = .numeric } struct Record: Encodable { let timestamp: Date let enabled: Bool } let records = [Record(timestamp: Date(), enabled: true)] let csv = try isoEncoder.encode(records, into: String.self) // Output: timestamp,enabled // 2024-01-15T10:30:00Z,1 ``` -------------------------------- ### CSVReader - Sequence Syntax Parsing Source: https://github.com/dehesa/codablecsv/blob/master/README.md Shows how to iterate over a CSVReader using Swift's Sequence protocol for a more idiomatic iteration experience. ```APIDOC ## CSVReader - Sequence Syntax Parsing ### Description Iterates over the `CSVReader` using Swift's `Sequence` protocol for a concise and idiomatic way to process each row. ### Method Iterates directly over a `CSVReader` instance using a `for-in` loop. ### Endpoint N/A (In-memory or stream parsing) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```swift let reader = try CSVReader(input: URL(...), configuration: ...) for row in reader { // Process each row: [String] } ``` ### Response #### Success Response (200) - **row** ([String]) - The current row being iterated over. ### Note This iteration method does not throw errors. If the CSV data is invalid, the loop may crash. Use `readRow()` for more robust error handling with potentially invalid data. ``` -------------------------------- ### Configure CSVWriter Initialization Source: https://github.com/dehesa/codablecsv/blob/master/README.md Initialize CSVWriter with custom configuration for delimiters, headers, encoding, and BOM strategy. ```swift let writer = CSVWriter(fileURL: ...) { $0.delimiters.row = "\r\n" $0.headers = ["Name", "Age", "Pet"] $0.encoding = .utf8 $0.bomStrategy = .never } ``` -------------------------------- ### Configure CSVDecoder with Custom Strategies Source: https://github.com/dehesa/codablecsv/blob/master/README.md Initializes a CSVDecoder with a custom configuration, specifying strategies for nil values, decimal formatting, data handling, buffering, trimming, encoding, and row delimiters. ```swift var config = CSVDecoder.Configuration() config.nilStrategy = .empty config.decimalStrategy = .locale(.current) config.dataStrategy = .base64 config.bufferingStrategy = .sequential config.trimStrategy = .whitespaces config.encoding = .utf16 config.delimiters.row = "\r\n" let decoder = CSVDecoder(configuration: config) ``` -------------------------------- ### Configure CSVReader Initialization Source: https://github.com/dehesa/codablecsv/blob/master/README.md Set CSVReader configuration properties using a closure during initialization. Ensure delimiters and escaping characters are not included in trim strategies. ```swift let reader = CSVReader(input: ...) { $0.encoding = .utf8 $0.delimiters.row = "\r\n" $0.headerStrategy = .firstLine $0.trimStrategy = .whitespaces } ``` -------------------------------- ### Configure CSVDecoder Initialization Source: https://github.com/dehesa/codablecsv/blob/master/README.md Customize decoding behavior by setting properties like encoding, delimiters, header strategy, and custom decimal decoding during CSVDecoder initialization. ```swift let decoder = CSVDecoder { $0.encoding = .utf8 $0.delimiters.field = "\t" $0.headerStrategy = .firstLine $0.bufferingStrategy = .keepAll $0.decimalStrategy = .custom({ let value = try Float(from: $0) return Decimal(value) }) } ``` -------------------------------- ### Configure CSVDecoder using a Closure Source: https://github.com/dehesa/codablecsv/blob/master/README.md Initializes a CSVDecoder using a convenience closure that allows modifying the configuration in-place. ```swift let decoder = CSVDecoder { $0.nilStrategy = .empty $0.decimalStrategy = .locale(.current) // and so on and so forth } ``` -------------------------------- ### Configure CSVEncoder with Custom Strategies Source: https://github.com/dehesa/codablecsv/blob/master/README.md Set custom strategies for delimiters, date formatting, float representation, and data encoding during CSVEncoder initialization. The `.headers` configuration is required when using keyed encoding containers. ```swift let encoder = CSVEncoder { $0.headers = ["name", "age", "hasPet"] $0.delimiters = (field: ";", row: "\r\n") $0.dateStrategy = .iso8601 $0.bufferingStrategy = .sequential $0.floatStrategy = .convert(positiveInfinity: "∞", negativeInfinity: "-∞", nan: "≁") $0.dataStrategy = .custom({ (data, encoder) in let string = customTransformation(data) var container = try encoder.singleValueContainer() try container.encode(string) }) } ``` -------------------------------- ### Configure CSV Writer Options Source: https://context7.com/dehesa/codablecsv/llms.txt Set various options for CSV writing, including encoding, BOM strategy, delimiters, escaping, and headers. Use the configuration object or closure syntax. ```swift import CodableCSV // Full configuration example var config = CSVWriter.Configuration() // Encoding: output character encoding config.encoding = .utf8 // config.encoding = .utf16 // BOM strategy: Byte Order Mark handling config.bomStrategy = .convention // Default: BOM only for UTF-16/32 // config.bomStrategy = .always // Always include BOM // config.bomStrategy = .never // Never include BOM // Delimiters: field and row separators config.delimiters = (field: ",", row: "\n") // Default // config.delimiters = (field: "\t", row: "\n") // TSV // config.delimiters = (field: ";", row: "\r\n") // European CSV // Escaping strategy config.escapingStrategy = .doubleQuote // Default: escape with " // config.escapingStrategy = .none // No escaping (error if delimiter in field) // Headers: optional header row config.headers = ["column1", "column2", "column3"] // config.headers = [] // No headers (default) // Using configuration let writer = try CSVWriter(configuration: config) // Or use closure syntax let writer2 = try CSVWriter { config in config.headers = ["id", "name", "value"] config.delimiters.row = "\r\n" config.encoding = .utf8 config.bomStrategy = .never } // Write to file with configuration let fileWriter = try CSVWriter( fileURL: URL(fileURLWithPath: "/tmp/output.csv"), append: false // Overwrite if exists ) { config.headers = ["timestamp", "event"] config.encoding = .utf8 } try fileWriter.write(row: ["2024-01-15", "started"]) try fileWriter.endEncoding() ``` -------------------------------- ### Import CodableCSV Source: https://github.com/dehesa/codablecsv/blob/master/README.md Include the module in your Swift source files. ```swift import CodableCSV ``` -------------------------------- ### CSVReader - Complete Input Parsing Source: https://github.com/dehesa/codablecsv/blob/master/README.md Demonstrates how to parse an entire CSV input at once and access headers, rows, records, columns, and individual fields. ```APIDOC ## CSVReader - Complete Input Parsing ### Description Parses the entire CSV input and provides access to headers, rows, records, columns, and fields. ### Method Static method `decode(input:)` on `CSVReader`. ### Endpoint N/A (In-memory parsing) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```swift let data: Data = ... try CSVReader.decode(input: data) ``` ### Response #### Success Response (200) - **headers** ([String]) - The header row of the CSV. - **rows** ([[String]]) - All rows of the CSV as arrays of strings. - **records** ([CSVRecord]) - All rows wrapped in `CSVRecord` for convenient access. - **columns** ([[String]]) - All columns of the CSV as arrays of strings. - **result[row: Int, column: Int]** (String) - Access a specific field by row and column index. - **result[row: Int, column: String]** (String?) - Access a specific field by row index and column header name. #### Response Example ```json { "headers": ["Name", "Age"], "rows": [["Alice", "30"], ["Bob", "25"]], "records": [ { "row": ["Alice", "30"], "fields": {"Name": "Alice", "Age": "30"} }, { "row": ["Bob", "25"], "fields": {"Name": "Bob", "Age": "25"} } ], "columns": [ ["Alice", "Bob"], ["30", "25"] ] } ``` ``` -------------------------------- ### CSVWriter Configuration Source: https://github.com/dehesa/codablecsv/blob/master/README.md Details on how to configure the CSVWriter instance using various properties like delimiters, headers, and encoding. ```APIDOC ## CSVWriter Configuration ### Description Configures the behavior of the CSVWriter instance during initialization. ### Parameters - **delimiters** (struct) - Optional - Specifies field and row delimiters (default: field: ",", row: "\n"). - **escapingStrategy** (enum) - Optional - Specifies the Unicode scalar used to escape fields (default: .doubleQuote). - **headers** (array) - Optional - Defines the header row for the CSV data (default: []). - **encoding** (String.Encoding) - Optional - Specifies the file encoding (default: nil). - **bomStrategy** (enum) - Optional - Indicates whether a Byte Order Marker is included (default: .convention). ### Request Example let writer = CSVWriter(fileURL: ...) { $0.delimiters.row = "\r\n" $0.headers = ["Name", "Age", "Pet"] $0.encoding = .utf8 $0.bomStrategy = .never } ``` -------------------------------- ### Write CSV data with CSVWriter Source: https://context7.com/dehesa/codablecsv/llms.txt Demonstrates field-by-field and row-by-row writing to memory buffers and files. ```swift import CodableCSV // Write to memory buffer let writer = try CSVWriter { config in config.headers = ["timestamp", "event", "value"] config.delimiters.row = "\r\n" // Windows-style line endings } // Write complete rows try writer.write(row: ["2024-01-15T10:30:00", "login", "user123"]) try writer.write(row: ["2024-01-15T10:31:00", "click", "button_a"]) // Write fields individually try writer.write(field: "2024-01-15T10:32:00") try writer.write(field: "purchase") try writer.write(field: "item_456") try writer.endRow() // Write multiple fields at once (without ending row) try writer.write(fields: ["2024-01-15T10:33:00", "logout"]) try writer.write(field: "user123") try writer.endRow() // Finalize and get data try writer.endEncoding() let csvData = try writer.data() print(String(data: csvData, encoding: .utf8)!) // Output: // timestamp,event,value // 2024-01-15T10:30:00,login,user123 // 2024-01-15T10:31:00,click,button_a // 2024-01-15T10:32:00,purchase,item_456 // 2024-01-15T10:33:00,logout,user123 // Write directly to file let fileWriter = try CSVWriter(fileURL: URL(fileURLWithPath: "/tmp/events.csv")) { config in config.headers = ["id", "name"] } try fileWriter.write(row: ["1", "First"]) try fileWriter.write(row: ["2", "Second"]) try fileWriter.endEncoding() ``` -------------------------------- ### Add CodableCSV via Cocoapods Source: https://github.com/dehesa/codablecsv/blob/master/README.md Add the library to your Podfile. ```ruby pod 'CodableCSV', '~> 0.6.7' ``` -------------------------------- ### Add CodableCSV via Swift Package Manager Source: https://github.com/dehesa/codablecsv/blob/master/README.md Include the library as a dependency in your Package.swift file. ```swift // swift-tools-version:5.1 import PackageDescription let package = Package( /* Your package name, supported platforms, and generated products go here */ dependencies: [ .package(url: "https://github.com/dehesa/CodableCSV.git", from: "0.6.7") ], targets: [ .target(name: /* Your target name here */, dependencies: ["CodableCSV"]) ] ) ``` -------------------------------- ### Decode CSV data with CSVDecoder Source: https://context7.com/dehesa/codablecsv/llms.txt Shows how to decode CSV strings into Decodable types using headers, custom strategies, and integer-based CodingKeys. ```swift import CodableCSV // Define a Codable type struct Student: Decodable { let name: String let age: Int let gpa: Double let isActive: Bool } let csvData = """ name,age,gpa,isActive Alice,22,3.8,true Bob,24,3.5,false Charlie,21,3.9,true """ // Basic decoding let decoder = CSVDecoder { config in config.headerStrategy = .firstLine } let students = try decoder.decode([Student].self, from: csvData) for student in students { print("\(student.name): Age \(student.age), GPA \(student.gpa)") } // Output: // Alice: Age 22, GPA 3.8 // Bob: Age 24, GPA 3.5 // Charlie: Age 21, GPA 3.9 // Decoding with custom strategies struct Transaction: Decodable { let id: Int let amount: Decimal let date: Date } let transactionCSV = """ id,amount,date 1,99.99,2024-01-15 2,149.50,2024-01-16 """ let transactionDecoder = CSVDecoder { config in config.headerStrategy = .firstLine config.decimalStrategy = .locale(.current) config.dateStrategy = .formatted({ let f = DateFormatter() f.dateFormat = "yyyy-MM-dd" return f }()) } let transactions = try transactionDecoder.decode([Transaction].self, from: transactionCSV) // Decoding with integer-based CodingKeys (no headers required) struct Record: Decodable { let field1: String let field2: Int private enum CodingKeys: Int, CodingKey { case field1 = 0 case field2 = 1 } } let noHeaderCSV = "hello,42\nworld,99" let noHeaderDecoder = CSVDecoder { config in config.headerStrategy = .none } let records = try noHeaderDecoder.decode([Record].self, from: noHeaderCSV) ``` -------------------------------- ### Lazy Encoding with Configuration and File URL Source: https://github.com/dehesa/codablecsv/blob/master/README.md Initialize a lazy CSV encoder with specific configurations and specify a file URL for output. This allows encoding multiple types of data sequentially into the same output. ```swift let encoder = CSVEncoder(configuration: config).lazy(into: fileURL) students.forEach { try encoder.encode($0) } teachers.forEach { try encoder.encode($0) } try encoder.endEncoding() ``` -------------------------------- ### Read CSV Row-by-Row Source: https://github.com/dehesa/codablecsv/blob/master/README.md Initialize CSVReader with an input and configure header strategy. Read rows or records individually until nil is returned. The reader cleans up memory upon scope exit. ```swift let reader = try CSVReader(input: string) { $0.headerStrategy = .firstLine } let rowA = try reader.readRow() ``` ```swift let string = "numA,numB,numC\n1,2,3\n4,5,6\n7,8,9" let headers: [String] = reader.headers // ["numA", "numB", "numC"] guard let rowB = try reader.readRow(), // ["4", "5", "6"] let rowC = try reader.readRow() /* ["7", "8", "9"] */ else { ... } ``` -------------------------------- ### CSVReader - Row-by-Row Parsing Source: https://github.com/dehesa/codablecsv/blob/master/README.md Illustrates how to read a CSV row by row, allowing for memory-efficient processing of large files and access to headers and records. ```APIDOC ## CSVReader - Row-by-Row Parsing ### Description Reads CSV data one row at a time, providing control over memory usage and access to headers and records. ### Method Initializes `CSVReader` with an input and uses `readRow()` or `readRecord()` to fetch rows sequentially. ### Endpoint N/A (In-memory or stream parsing) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```swift let string = "numA,numB,numC\n1,2,3\n4,5,6\n7,8,9" try CSVReader(input: string) { $0.headerStrategy = .firstLine } reader.readRow() reader.readRecord() ``` ### Response #### Success Response (200) - **headers** ([String]) - The header row of the CSV (available after initialization). - **readRow()** ([String]?) - Returns the next row as an array of strings, or `nil` if end of file is reached. - **readRecord()** (CSVRecord?) - Returns the next row wrapped in a `CSVRecord` for convenient field access by index or header name, or `nil` if end of file is reached. #### Response Example ```json // For readRow(): ["4", "5", "6"] // For readRecord(): { "row": ["1", "2", "3"], "fields": {"numA": "1", "numB": "2", "numC": "3"} } ``` ``` -------------------------------- ### Configure CSV Decoder Options Source: https://context7.com/dehesa/codablecsv/llms.txt Customize CSV decoding with strategies for nil values, booleans, floats, decimals, dates, and data. Configure reader settings like header strategy and delimiters. ```swift import CodableCSV let decoder = CSVDecoder { config in // Reader configuration (inherited) config.headerStrategy = .firstLine config.encoding = .utf8 config.delimiters = (field: ",", row: "\n") config.trimStrategy = .whitespaces // Nil strategy: how empty/missing values are handled config.nilStrategy = .empty // Default: empty string = nil // config.nilStrategy = .custom(["null", "NULL", "N/A"]) // Boolean strategy config.boolStrategy = .insensitive // Default: true/false case-insensitive // config.boolStrategy = .numeric // 0 = false, non-zero = true // Non-conforming float strategy (NaN, Infinity) config.nonConformingFloatStrategy = .throw // Default: throw on NaN/Inf // config.nonConformingFloatStrategy = .convert( // positiveInfinity: "Inf", // negativeInfinity: "-Inf", // nan: "NaN" // ) // Decimal strategy config.decimalStrategy = .locale(.current) // Use locale for parsing // config.decimalStrategy = .custom { decoder in ... } // Date strategy config.dateStrategy = .deferredToDate // Default: use Date's Decodable // config.dateStrategy = .iso8601 // config.dateStrategy = .secondsSince1970 // config.dateStrategy = .millisecondsSince1970 // config.dateStrategy = .formatted(myDateFormatter) // config.dateStrategy = .custom { decoder in ... } // Data strategy (for Data fields) config.dataStrategy = .base64 // Default: Base64 encoded strings // config.dataStrategy = .custom { decoder in ... } // Buffering strategy (affects memory usage) config.bufferingStrategy = .keepAll // Default: keep all rows in memory // config.bufferingStrategy = .sequential // Only keep current row (for lazy) // config.bufferingStrategy = .unrequested // Discard rows not requested } // Example with custom date formatter let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" let customDecoder = CSVDecoder { config in config.headerStrategy = .firstLine config.dateStrategy = .formatted(dateFormatter) config.nilStrategy = .custom(["", "null", "NULL", "N/A"]) } ``` -------------------------------- ### Dynamically Set CSVDecoder Configuration Source: https://github.com/dehesa/codablecsv/blob/master/README.md Sets CSVDecoder configuration values dynamically after initialization using @dynamicMemberLookup, allowing for flexible adjustments before decoding. ```swift let decoder = CSVDecoder() decoder.bufferingStrategy = .sequential decoder.decode([Student].self, from: url1) decoder.bufferingStrategy = .keepAll decoder.decode([Pets].self, from: url2) ``` -------------------------------- ### CSVReader Configuration via Closure Source: https://context7.com/dehesa/codablecsv/llms.txt Configures a CSV reader using a closure, allowing for concise modification of specific settings like header strategy, delimiters, trimming, and encoding. ```swift // Or use closure syntax let reader2 = try CSVReader(input: csvData) { config in config.headerStrategy = .firstLine config.delimiters.field = ";" config.trimStrategy = .whitespaces config.encoding = .utf8 } ``` -------------------------------- ### Handle CSV Reading Errors Source: https://context7.com/dehesa/codablecsv/llms.txt Demonstrates how to catch and inspect `CSVError` during CSV reading operations. This includes identifying the error type, failure reason, help text, and user info for debugging. ```swift import CodableCSV // Reading errors do { let invalidCSV = """ name,age Alice,30 Bob,25,extra_field """ let _ = try CSVReader.decode(input: invalidCSV) { $0.headerStrategy = .firstLine } } catch let error as CSVError { print("Error type: \(error.type)") print("Reason: \(error.failureReason ?? "Unknown")") print("Help: \(error.helpAnchor ?? "None")") print("Details: \(error.errorUserInfo)") } ``` -------------------------------- ### Lazy CSV Encoding to String Source: https://context7.com/dehesa/codablecsv/llms.txt Demonstrates lazy encoding of CSV data directly into a String. Useful for smaller datasets or when the output needs to be manipulated as a string before further processing. ```swift // Lazy encoding to String let stringEncoder = try CSVEncoder { $0.headers = ["a", "b"] }.lazy(into: String.self) struct Point: Encodable { let a: Int; let b: Int } try stringEncoder.encodeRow(Point(a: 1, b: 2)) try stringEncoder.encodeRow(Point(a: 3, b: 4)) let result = try stringEncoder.endEncoding() // Returns String ``` -------------------------------- ### Parse CSV using Sequence Syntax Source: https://github.com/dehesa/codablecsv/blob/master/README.md Iterate over a CSVReader using a for-in loop for Sequence syntax. This method does not throw errors and will crash on invalid data; use readRow() for controlled error handling. ```swift let reader = try CSVReader(input: URL(...), configuration: ...) for row in reader { // Do something with the row: [String] } ``` -------------------------------- ### CSVDecoder Usage Source: https://github.com/dehesa/codablecsv/blob/master/README.md Explains how to use CSVDecoder to transform CSV data into Swift types conforming to Decodable. ```APIDOC ## CSVDecoder ### Description Transforms CSV data into a Swift type conforming to Decodable. ### Method - **decode** (function) - Decodes CSV data from Data, String, URL, or InputStream. ### Request Example let decoder = CSVDecoder() let result = try decoder.decode(CustomType.self, from: data) ``` -------------------------------- ### Define a Codable Student Structure Source: https://github.com/dehesa/codablecsv/blob/master/README.md Define a Swift struct that conforms to Codable to represent a student with name, age, and pet ownership. This structure can be directly decoded from or encoded to CSV data. ```swift struct Student: Codable { var name: String var age: Int var hasPet: Bool } ``` -------------------------------- ### Parse CSV Row-by-Row with CSVReader Source: https://context7.com/dehesa/codablecsv/llms.txt Provides sequential parsing for memory-efficient processing. Supports iteration via Sequence or manual read methods. ```swift import CodableCSV let csvData = """ id,product,price 1,Widget,19.99 2,Gadget,29.99 3,Gizmo,39.99 """.data(using: .utf8)! // Create reader with configuration let reader = try CSVReader(input: csvData) { config in config.headerStrategy = .firstLine config.encoding = .utf8 } // Access headers after initialization let headers = reader.headers // ["id", "product", "price"] // Read rows one at a time with error handling while let row = try reader.readRow() { print("Product: \(row[1]), Price: $\(row[2])") } // Output: // Product: Widget, Price: $19.99 // Product: Gadget, Price: $29.99 // Product: Gizmo, Price: $39.99 // Alternative: Use readRecord() for header-based field access let reader2 = try CSVReader(input: csvData) { $0.headerStrategy = .firstLine } while let record = try reader2.readRecord() { if let product = record["product"], let price = record["price"] { print("\(product): $\(price)") } } // Alternative: Use Sequence syntax (crashes on invalid data) let reader3 = try CSVReader(input: csvData) { $0.headerStrategy = .firstLine } for row in reader3 { print(row) } ``` -------------------------------- ### Lazy Encoding with Sequential Buffering Source: https://github.com/dehesa/codablecsv/blob/master/README.md Optimize memory usage for lazy encoding by setting the buffering strategy to `.sequential`. This is particularly effective when encoding many rows sequentially. ```swift let encoder = CSVEncoder { $0.bufferingStrategy = .sequential }.lazy(into: String.self) ``` -------------------------------- ### Configure CSVEncoder with Explicit Headers Source: https://github.com/dehesa/codablecsv/blob/master/README.md Configures a CSVEncoder to use explicitly defined headers by mapping all cases from a CodingKeys enum to their raw string values. ```swift let encoder = CSVEncoder { $0.headers = Student.CodingKeys.allCases.map { $0.rawValue } } ``` -------------------------------- ### CSV Encoding with Custom Strategies Source: https://context7.com/dehesa/codablecsv/llms.txt Encodes Swift types conforming to Encodable into CSV format using custom strategies for date, data, and nil values. ```swift import CodableCSV struct Event: Encodable { let name: String let timestamp: Date let metadata: Data? } let events = [ Event(name: "login", timestamp: Date(), metadata: "user123".data(using: .utf8)) ] let eventEncoder = CSVEncoder { config.headers = ["name", "timestamp", "metadata"] config.dateStrategy = .iso8601 config.dataStrategy = .base64 config.nilStrategy = .empty } let eventCSV = try eventEncoder.encode(events, into: String.self) ``` -------------------------------- ### Custom Nil Strategy for CSV Decoding Source: https://github.com/dehesa/codablecsv/blob/master/README.md Implements a custom nil strategy for CSV decoding where empty fields are encoded as the string 'null' using a single value container. ```swift let decoder = CSVDecoder() decoder.nilStrategy = .custom({ var container = encoder.singleValueContainer() try container.encode("null") }) ``` -------------------------------- ### Define Flat Codable Structure Source: https://github.com/dehesa/codablecsv/blob/master/README.md Defines a flat structure for Codable conformance, avoiding the need for custom initializers by directly mapping properties to enum cases. ```swift struct Student: Codable { var name: String var age: Int var nickname: String var gender: Gender enum Gender: Int, Codable { case male = 1 case female = 2 } } ``` -------------------------------- ### Handle CSV Writing Errors Source: https://context7.com/dehesa/codablecsv/llms.txt Illustrates catching `CSVError` during CSV writing, specifically when attempting to write a field containing delimiters without proper escaping. ```swift import CodableCSV // Writing errors do { let writer = try CSVWriter { $0.escapingStrategy = .none } try writer.write(field: "field,with,commas") // Error: delimiter in unescaped field } catch let error as CSVError { print("Write error: \(error.localizedDescription)") } ``` -------------------------------- ### Decode CSV from File URL with CSVDecoder Source: https://github.com/dehesa/codablecsv/blob/master/README.md Decode CSV data directly from a file URL using CSVDecoder. Configure buffering strategy for large files. ```swift let decoder = CSVDecoder { $0.bufferingStrategy = .sequential } let content = try decoder.decode([Student].self, from: URL("~/Desktop/Student.csv")) ``` -------------------------------- ### CSVError Handling Source: https://github.com/dehesa/codablecsv/blob/master/README.md Overview of the CSVError structure used for handling failures in CodableCSV operations. ```APIDOC ## CSVError ### Description Represents errors thrown by CodableCSV operations, providing rich diagnostic information. ### Properties - **type** (enum) - The error group category. - **failureReason** (string) - Explanation of what went wrong. - **helpAnchor** (string) - Advice on how to solve the problem. - **errorUserInfo** (dictionary) - Arguments associated with the operation. - **underlyingError** (Error) - Optional underlying error. ### Response Example do { let writer = try CSVWriter() try writer.write(row: row) } catch let error as CSVError { print(error.localizedDescription) } ``` -------------------------------- ### Define Type-Safe Coding Keys Source: https://github.com/dehesa/codablecsv/blob/master/README.md Defines a struct with explicit CodingKeys conforming to String, CaseIterable for type-safe header generation in CSV encoding. ```swift struct Student { var name: String var age: Int var hasPet: Bool enum CodingKeys: String, CodingKey, CaseIterable { case name, age, hasPet } } ``` -------------------------------- ### Decode CSV Data Completely Source: https://github.com/dehesa/codablecsv/blob/master/README.md Use CSVReader.decode(input:) for high-level parsing of an entire CSV input. Access headers, rows, records, columns, and fields after decoding. ```swift let data: Data = ... let result = try CSVReader.decode(input: data) ``` ```swift let headers: [String] = result.headers let rows = result.rows let row = result[0] let records = result.records let record = result[record: 0] let columns = result.columns let column = result[column: 0] let column = result[column: "Name"] let fieldB: String = result[row: 3, column: 2] let fieldA: String? = result[row: 2, column: "Age"] ``` -------------------------------- ### Handle CSV Decoding Errors Source: https://context7.com/dehesa/codablecsv/llms.txt Shows how to catch `CSVError` when decoding CSV data into Swift types, such as when a field cannot be converted to the expected type (e.g., a string to an integer). ```swift import CodableCSV // Decoding errors do { struct Person: Decodable { let name: String; let age: Int } let badCSV = "name,age\nAlice,not_a_number" let decoder = CSVDecoder { $0.headerStrategy = .firstLine } let _ = try decoder.decode([Person].self, from: badCSV) } catch let error as CSVError { print("Decode error: \(error.localizedDescription)") } ``` -------------------------------- ### Specify Integer Coding Keys for CSV Decoding Source: https://github.com/dehesa/codablecsv/blob/master/README.md When CSV data lacks a header row, define a private CodingKeys enum conforming to Int and CodingKey to map properties to column indices. This improves performance by skipping header matching. ```swift struct Student: Codable { var name: String var age: Int var hasPet: Bool private enum CodingKeys: Int, CodingKey { case name = 0 case age = 1 case hasPet = 2 } } ``` -------------------------------- ### CSVReader.decode - Complete File Parsing Source: https://context7.com/dehesa/codablecsv/llms.txt Parses an entire CSV file into a FileView structure, suitable for small to medium-sized files. Provides easy access to headers, rows, and columns. ```APIDOC ## CSVReader.decode - Complete File Parsing ### Description Parses an entire CSV file at once and returns a `FileView` structure providing convenient access to headers, rows, columns, and individual fields. This high-level API is ideal for small to medium-sized files that fit comfortably in memory. ### Method `CSVReader.decode` ### Endpoint N/A (In-memory operation) ### Parameters #### Query Parameters - **input** (String or Data or URL or InputStream) - Required - The CSV data source. - **configuration** (Closure) - Optional - Configuration closure for `CSVConfig`. - **headerStrategy** (HeaderStrategy) - Optional - Strategy for handling headers (e.g., `.firstLine`). - **delimiters** (Delimiters) - Optional - Field and row delimiters. - **encoding** (String.Encoding) - Optional - Character encoding. - **escaping** (Escaping) - Optional - Escaping rules. - **trimming** (Trimming) - Optional - Trimming rules. ### Request Example ```swift import CodableCSV let csvString = """ name,age,city Alice,30,New York Bob,25,Los Angeles Charlie,35,Chicago """ let result = try CSVReader.decode(input: csvString) { config in config.headerStrategy = .firstLine } ``` ### Response #### Success Response (200) - **FileView** - A structure containing headers, rows, and columns. - **headers** ([String]) - An array of header names. - **rows** ([[String]]) - An array of rows, where each row is an array of strings. #### Response Example ```json { "headers": ["name", "age", "city"], "rows": [ ["Alice", "30", "New York"], ["Bob", "25", "Los Angeles"], ["Charlie", "35", "Chicago"] ] } ``` ### Usage Examples ```swift // Access headers let headers = result.headers // Access rows by index let firstRow = result[0] // Access specific field by row and column index let age = result[row: 1, column: 1] // Access specific field by row index and header name let city = result[row: 2, column: "city"] // Access entire column by header name let allNames = result[column: "name"] // Iterate through all rows for row in result.rows { print(row.joined(separator: " | ")) } ``` ``` -------------------------------- ### Parse CSV with CSVReader.decode Source: https://context7.com/dehesa/codablecsv/llms.txt Parses an entire CSV file into a FileView structure for convenient access to headers, rows, and columns. Best suited for small to medium-sized files that fit in memory. ```swift import CodableCSV // Sample CSV data let csvString = """ name,age,city Alice,30,New York Bob,25,Los Angeles Charlie,35,Chicago """ // Decode entire CSV file with headers let result = try CSVReader.decode(input: csvString) { config in config.headerStrategy = .firstLine } // Access headers let headers = result.headers // ["name", "age", "city"] // Access rows by index let firstRow = result[0] // ["Alice", "30", "New York"] // Access specific field by row and column index let age = result[row: 1, column: 1] // "25" // Access specific field by row index and header name let city = result[row: 2, column: "city"] // Optional("Chicago") // Access entire column by header name let allNames = result[column: "name"] // Optional(["Alice", "Bob", "Charlie"]) // Iterate through all rows for row in result.rows { print(row.joined(separator: " | ")) } // Output: // Alice | 30 | New York // Bob | 25 | Los Angeles // Charlie | 35 | Chicago ``` -------------------------------- ### Decode CSV Data into Swift Objects Source: https://github.com/dehesa/codablecsv/blob/master/README.md Use CSVDecoder to parse a CSV string into an array of Codable objects. Ensure the CSV string includes a header row for automatic decoding, or configure the decoder to use a specific header strategy. ```swift let string = """ name,age,hasPet John,22,true Marine,23,false Alta,24,true """ let decoder = CSVDecoder { $0.headerStrategy = .firstLine } let students = try decoder.decode([Student].self, from: string) ``` -------------------------------- ### Define Nested Codable Structures for Complex Data Source: https://github.com/dehesa/codablecsv/blob/master/README.md Represent nested data structures like a school with students and pets by defining corresponding Codable structs. Note that default CSV decoding may not support deep nesting directly. ```swift struct School: Codable { let students: [Student] } struct Student: Codable { var name: String var age: Int var pet: Pet } struct Pet: Codable { var nickname: String var gender: Gender enum Gender: Codable { case male, female } } ``` -------------------------------- ### Encode CSV Row by Row Source: https://github.com/dehesa/codablecsv/blob/master/README.md Write CSV data row by row to a file or a buffer. Use 'endEncoding()' to finalize the CSV writing process. The writer can be initialized with a file URL or a configuration closure. ```swift let writer = try CSVWriter(fileURL: URL("~/Desktop/Test.csv")!, append: false) for row in input { try writer.write(row: row) } try writer.endEncoding() ``` ```swift let writer = try CSVWriter { $0.headers = input[0] } for row in input.dropFirst() { try writer.write(row: row) } try writer.endEncoding() let result = try writer.data() ``` -------------------------------- ### CSVReader for Tab-Separated Values (TSV) Source: https://context7.com/dehesa/codablecsv/llms.txt Parses tab-separated values (TSV) by configuring the CSV reader with a tab delimiter for fields and specifying that the first line contains headers. ```swift // Parse tab-separated values let tsvData = "name\tage\tacti\nAlice\t30\ttrue" let tsvReader = try CSVReader(input: tsvData) { $0.headerStrategy = .firstLine $0.delimiters.field = "\t" } ``` -------------------------------- ### Decode CSV Data with CSVDecoder Source: https://github.com/dehesa/codablecsv/blob/master/README.md Use CSVDecoder to transform CSV data into a Swift Decodable type. The decoder can handle various data sources. ```swift let decoder = CSVDecoder() let result = try decoder.decode(CustomType.self, from: data) ``` -------------------------------- ### Encode Swift Objects to CSV Data Source: https://github.com/dehesa/codablecsv/blob/master/README.md Use CSVEncoder to convert an array of Codable objects into a CSV formatted string. Specify the desired headers for the output CSV. ```swift let encoder = CSVEncoder { $0.headers = ["name", "age", "hasPet"] } let newData = try encoder.encode(students) ``` -------------------------------- ### Lazy CSV Decoding Row-by-Row Source: https://github.com/dehesa/codablecsv/blob/master/README.md Decode CSV input row-by-row on demand using the `lazy(from:)` function. This approach is memory-efficient for large files and allows switching decoded types. ```swift let decoder = CSVDecoder(configuration: config).lazy(from: fileURL) let student1 = try decoder.decodeRow(Student.self) let student2 = try decoder.decodeRow(Student.self) ``` ```swift let decoder = CSVDecoder().lazy(from: fileData) let students = try decoder.map { try $0.decode(Student.self) } ``` ```swift let decoder = CSVDecoder().lazy(from: fileString) // The first 100 rows are students. let students = ( 0..<100).map { _ in try decoder.decode(Student.self) } // The second 100 rows are teachers. let teachers = (100..<110).map { _ in try decoder.decode(Teacher.self) } ``` ```swift let decoder = CSVDecoder { $0.headerStrategy = .firstLine $0.bufferingStrategy = .sequential }.lazy(from: fileURL) ``` -------------------------------- ### Handle CSVWriter Errors Source: https://github.com/dehesa/codablecsv/blob/master/README.md Catch and print CSVWriter errors using a do-catch block. Errors provide detailed information for debugging. ```swift do { let writer = try CSVWriter() for row in customData { try writer.write(row: row) } } catch let error { print(error) } ```