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: "")
}
@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