How to read user input or character stream from standard input in Swift for Linux?
readLine() works on Ubuntu 15:
[Readline] Returns
Character
s read from standard input through the end of the current line or until EOF is reached, ornil
if EOF has already been reached.
Example:
print("\nEnter your name:\n")
if let name = readLine() {
print("\nHello \(name)!\n")
}
ed@swiftux:~/Swift/Scripts$ ./testReadline
Enter your name:
Eric
Hello Eric!
readline()
also works with |
(the pipe):
ed@swiftux:~/Swift/Scripts$ echo "Mike" | ./testReadline
Enter your name:
Hello Mike!
I've also tried the classic way with NSFileHandle but it's not implemented yet:
fatal error: availableData is not yet implemented: file Foundation/NSObjCRuntime.swift
If you import Glibc on Linux and Darwin.C on macOS, then you can read one line at a time using the getline
function.
This requires a wee bit of c interop, but you can wrap it up to present a more Swifty interface. For instance, the following function returns a generator that iterates over lines read from a file stream:
#if os(Linux)
import Glibc
#else
import Darwin.C
#endif
func lineGenerator(file:UnsafeMutablePointer<FILE>) -> AnyIterator<String>
{
return AnyIterator { () -> String? in
var line:UnsafeMutablePointer<CChar>? = nil
var linecap:Int = 0
defer { free(line) }
let charactersWritten = getline(&line, &linecap, file)
if charactersWritten > 0 {
guard let line = line else { return nil }
return String(validatingUTF8: line)
}
else {
return nil
}
}
}
This works on Swift 3. You can find a small swiftecho example project which exercises this from the command line.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With