Xcode 6, Swift - Read Standard Input (Console) to String

Input from the keyboard in command line application

I managed to figure it out without dropping down in to C:

My solution is as follows:

func input() -> String {
var keyboard = NSFileHandle.fileHandleWithStandardInput()
var inputData = keyboard.availableData
return NSString(data: inputData, encoding:NSUTF8StringEncoding)!
}

More recent versions of Xcode need an explicit typecast (works in Xcode 6.4):

func input() -> String {
var keyboard = NSFileHandle.fileHandleWithStandardInput()
var inputData = keyboard.availableData
return NSString(data: inputData, encoding:NSUTF8StringEncoding)! as String
}

Swift's readLine() is nil when I enter a long string in STDIN

readLine() is a wrapper around the stdio getline function, and that function requires
only that a newline character occurs within the first SSIZE_MAX characters of the input. On the 64-bit OS X platform, SSIZE_MAX
is 2^63 - 1 which means that this is only a theoretical limitation.

So readLine() is not the problem, it can read arbitrarily long lines as long as they fit into your computers memory.

But it seems that you can not paste more than 1023 characters into the
Xcode debugger console. (Edit: This was also observed at Read a very long console input in C++).

Running the program in a Terminal with input redirection from a file is one option to solve the problem:

$ ./myProgram < /path/to/inputData.txt

Another option is to add

freopen("/path/to/your/inputData.txt", "r", stdin)

at the beginning of the Swift program. This redirects the standard
input to read from the given file.
The advantage of this method is that you can still debug your program
in Xcode.

Swift: How to read standard output in a child process without waiting for process to finish

You are reading synchronously on the main thread, therefore the UI is not updated until the function returns to the main loop.

There are (at least) two possible approaches to solve the problem:

  • Do the reading from the pipe on a background thread (e.g. by dispatching it to a background queue – but don't forget
    to dispatch the UI updates to the main thread again).
  • Use notifications to read asynchronously from the pipe (see
    Real time NSTask output to NSTextView with Swift for an example).


Related Topics



Leave a reply



Submit