[swift-users] file io in Swift 2.2 for Linux (would like to be pointed in the right direction)

Matthias Zenger matthias at objecthub.net
Sun Jun 5 16:04:28 CDT 2016


Quinn, Jens, thanks for pointing me at the NSStream classes. For some
reason, I discarded NSStream quickly after seeing the first paragraph
of Apple's
documentation on output streams
<https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Streams/Articles/WritingOutputStreams.html>
listing 5 relatively complex steps — without realizing that this API also
has a synchronous interface.

Obviously, the NSStream API is too low level and thus difficult to use.
Therefore, I would also like to see Apple build a great IO streaming API
for Swift. I've implemented Quinn's example using NSInputStream and Swift's
Generator design pattern. Except for mapping NSInputStream to a generator —
which is really messy — everything else is straightforward and much more
extensible and scalable than the standard Foundation approach. The code is
below.

== Matthias

See https://gist.github.com/objecthub/ada1f852924b2c253653d6949fd3555d

class ByteGenerator: GeneratorType {

  typealias Element = UInt8

  let input: NSInputStream

  var buffer: [UInt8]

  var index: Int = 0

  var eof: Bool = true

  init?(path: String, capacity: Int = 1024) {

    guard let input = NSInputStream(fileAtPath: path) else {

      return nil

    }

    self.buffer = [UInt8](count: capacity, repeatedValue: 0)

    input.open()

    if input.hasBytesAvailable {

      self.eof = input.read(&self.buffer, maxLength: self.buffer.count *
sizeof(UInt8)) <= 0

    }

    self.input = input

  }

  deinit {

    input.close()

  }

  func next() -> UInt8? {

    guard !self.eof else {

      return nil

    }

    if self.index >= self.buffer.count {

      self.index = 0

      self.eof = !input.hasBytesAvailable ||

                 input.read(&self.buffer, maxLength: self.buffer.count *
sizeof(UInt8)) <= 0

      guard !self.eof else {

        return nil

      }

    }

    self.index += 1

    return self.buffer[self.index - 1]

  }

}


struct CharacterGenerator<G: GeneratorType, U: UnicodeCodecType where
G.Element == U.CodeUnit>: GeneratorType {

  typealias Element = Character

  var source: G

  var decoder: U

  mutating func next() -> Character? {

    guard case .Result(let scalar) = self.decoder.decode(&self.source) else
{

      return nil

    }

    return Character(scalar)

  }

}


struct LineGenerator<G: GeneratorType where G.Element == Character>:
GeneratorType {

  typealias Element = String

  var source: G

  mutating func next() -> String? {

    guard let fst = source.next() else {

      return nil

    }

    guard fst != "\n" else {

      return ""

    }

    var line = String(fst)

    while let ch = source.next() {

      if (ch == "\n") {

        return line

      }

      line.append(ch)

    }

    return line

  }

}


if let input = ByteGenerator(path: "/Users/username/filename.txt") {

  var generator = LineGenerator(source: CharacterGenerator(source: input,
decoder: UTF8()))

  var i = 0

  while let line = generator.next() {

    print("\(i): \(line)")

    i += 1

  }

}







*Matthias Zenger* matthias at objecthub.net


On Sun, Jun 5, 2016 at 8:36 PM, Jens Alfke <jens at mooseyard.com> wrote:

>
> On Jun 4, 2016, at 6:25 PM, Matthias Zenger via swift-users <
> swift-users at swift.org> wrote:
>
> I wanted to use NSFileHandle (for a use case that requires streaming) and
> realized that this is an API that cannot really be used in Swift because
> it's based on Objective-C exceptions.
>
>
> You’re right, NSFileHandle is a very archaic class (kind of a coelacanth)
> and its I/O methods signal errors by throwing exceptions. It’s almost
> unique in that regard; in general Cocoa APIs are only supposed to throw
> exceptions for programmer errors like assertion failures.
>
> Are there any alternatives?
>
>
> NSStream.
>
> —Jens
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160605/f4cc73fd/attachment.html>


More information about the swift-users mailing list