Skip to content

Instantly share code, notes, and snippets.

@algal
Last active February 8, 2023 16:14
Show Gist options
  • Save algal/23b10062a558aec7679e4c854096f88e to your computer and use it in GitHub Desktop.
Save algal/23b10062a558aec7679e4c854096f88e to your computer and use it in GitHub Desktop.
Read a file one line at a time in Swift
import Darwin
/**
Returns a lazy sequence that returns a String for every line of `file`.
Example 1:
// print all lines from a file
let file = fopen(NSBundle.mainBundle().pathForResource("Cartfile", ofType: nil)!,"r")
for line in lineGenerator(file) { print(line,separator: "", terminator: "") }
fclose(file)
Example 2:
// echo lines from stdin
for line in lineGenerator(stdin) { print(line, separator: "", terminator: "") }
*/
func lineGenerator(file:UnsafeMutablePointer<FILE>) -> AnyGenerator<String>
{
return AnyGenerator { () -> String? in
var line:UnsafeMutablePointer<CChar> = nil
var linecap:Int = 0
defer { free(line) }
return getline(&line, &linecap, file) > 0 ? String.fromCString(line) : nil
}
}
let p = "/path/to/file" // could be returned by NSBundle.pathForResource, if we were using Foundation
let f = fopen(p,"r")
let g = lineGenerator(f)
for line in g {
// suppress print's automatic line ending, since
// lineGenerator captures every line's own new line character.
print(line, separator: "", terminator: "")
}
@algal
Copy link
Author

algal commented May 1, 2016

Note: From Rev 5 to Rev 6 (posted 2016-04-30T21:36PST), I changed line 22, which frees the temporary line buffer created by getline.

I believe the earlier line line.destroy() was incorrect, or at least probably incorrect, since it's not clear to me what the Swift docs mean by "object" in that context. Does line.destroy() destroy the C array starting at that char or just the first char?

But since the buffer is created by getline, it's created by malloc or its friends so free should be the correct balancing call.

@cham-s
Copy link

cham-s commented Aug 4, 2017

Your snippet made me learn more about Sequence and how to define a custom one.
Thanks!

@AlexandrGraschenkov
Copy link

Wrapped your code inside swift class in this gist

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment