StreamReader для URL-адресов серверов

Я работал с формой кода этот ответ, предоставленный Мартином Р. Код является удивительным, и это очень полезно. Однако он не работает со ссылками, отлично работает с файлами. После размещения некоторых NSLogs и разрывов я действительно обнаружил, что проблема заключается в этом кодовом блоке:

init?(path: String, delimiter: String = "\n", encoding: UInt = NSUTF8StringEncoding, chunkSize : Int = 4096) {
    self.chunkSize = chunkSize
    self.encoding = encoding

    self.fileHandle = NSFileHandle(forReadingFromURL: NSURL(string: path)!, error: nil)
    println("PATH IS \(path)")
    println("FILE HANDLE IS \(fileHandle)")
    if self.fileHandle == nil {
        println("FILE HANDLE IS NIL!")
        return nil
    }

В приведенном выше коде фактически содержатся некоторые незначительные изменения по сравнению с ответом Мартина. Также Apple говорит, что можно использовать fileHandle с forReadingFromURL, и он не должен возвращать нуль.  Но вот консольный вывод:

PATH IS http://smth.com
   FILE HANDLE IS nil
   FILE HANDLE IS NIL!!!!!

Вопрос в том, что неправильно?

UPDATE

Как любезно объяснил мне Martin R, этот код не будет работать с URL-адресами, этот ответ утверждает то же самое, поэтому я переписал код, руководствуясь предыдущие ответы:

import Foundation
import Cocoa

class StreamReader  {

let encoding : UInt
let chunkSize : Int
var atEof : Bool = false
var streamData : NSData!
var fileLength : Int
var urlRequest : NSMutableURLRequest
var currentOffset : Int
var streamResponse : NSString

var fileHandle : NSFileHandle!
let buffer : NSMutableData!
let delimData : NSData!

var reponseError: NSError?
var response: NSURLResponse?

init?(path: NSURL, delimiter: String = "\n", encoding: UInt = NSUTF8StringEncoding, chunkSize : Int = 10001000) {
    println("YOUR PATH IS \(path)")

    self.chunkSize = chunkSize
    self.encoding = encoding
    self.currentOffset = 0
    urlRequest = NSMutableURLRequest(URL: path)
    streamData = NSURLConnection.sendSynchronousRequest(urlRequest, returningResponse:&response, error:&reponseError)
    streamResponse = NSString(data:streamData!, encoding:NSUTF8StringEncoding)!
    self.fileLength = streamData.length
    //println("WHAT IS STREAMDATA \(streamData)")
    //println("WHAT IS URLREQUEST \(urlRequest)")

    if streamData == nil {
        println("LINK HAS NO CONTENT!!!!!")
    }

            self.fileLength = streamResponse.length
    println("FILE LENGTH IS \(fileLength)")
    self.buffer = NSMutableData(capacity: chunkSize)!

    // Create NSData object containing the line delimiter:
    delimData = delimiter.dataUsingEncoding(NSUTF8StringEncoding)!
    println("WHAT DOES THE DELIMITER \(delimiter)LOOK LIKE?")
    println("WHAT IS DELIMDATA \(delimData)")
}

deinit {
    self.close()
}

/// Return next line, or nil on EOF.
func nextLine() -> String? {

    if atEof {
        println("AT THE END OF YOUR FILE!!!")
        return nil
    }
    // Read data chunks from file until a line delimiter is found:

    if currentOffset >= fileLength {
        return nil
    }
    var blockLength : Int = buffer.length

    var range = buffer.rangeOfData(delimData, options: NSDataSearchOptions(0), range: NSMakeRange(currentOffset, blockLength))
            //println("STREAM DATA \(streamData)")

    println("RANGE IS \(range)")
    while range.location == NSNotFound {
        var nRange = NSMakeRange(currentOffset, chunkSize)
        println("nRange is \(nRange)")
        var tmpData = streamData.subdataWithRange(nRange)
        //println("TMP data length \(tmpData.length)")
        currentOffset += blockLength
        //println("TMPDATA is \(tmpData)")
        if tmpData.length == 0 {
            // EOF or read error.
            println("ERROR ????")
            atEof = true
            if buffer.length > 0 {
                // Buffer contains last line in file (not terminated by delimiter).
                let line = NSString(data: buffer, encoding: encoding);
                buffer.length = 0
                println("THE LINE IS \(line)")
                return line
            }
            // No more lines.
            return nil
        }
        buffer.appendData(tmpData)
        range = buffer.rangeOfData(delimData, options: NSDataSearchOptions(0), range: NSMakeRange(0, buffer.length))
    }

    // Convert complete line (excluding the delimiter) to a string:
    let line = NSString(data: buffer.subdataWithRange(NSMakeRange(0, range.location)),
        encoding: encoding)
    // Remove line (and the delimiter) from the buffer:
    buffer.replaceBytesInRange(NSMakeRange(0, range.location + range.length), withBytes: nil, length: 0)

    return line
}

/// Start reading from the beginning of file.
func rewind() -> Void {
    //streamData.seekToFileOffset(0)
    buffer.length = 0
    atEof = false
}

/// Close the underlying file. No reading must be done after calling this method.
func close() -> Void {
    if streamData != nil {
        streamData = nil
    }
}
}

extension StreamReader : SequenceType {
func generate() -> GeneratorOf<String> {
    return GeneratorOf<String> {
        return self.nextLine()
    }
}
}

Но на самом деле этот код очень далек от совершенства, и я хотел бы видеть какие-либо рекомендации по его улучшению. Пожалуйста, будь добр. Я очень любитель и очень неопытен (но рано или поздно я узнаю его)

Наконец, он работает. И, вероятно, последняя проблема остается, код не останавливается, он продолжает читать файл с самого начала.

Итак, теперь вопрос, вероятно, ближе к "Что не так с моим кодом?", по сравнению с предыдущим: "Что не так?"

UPDATE

Я переписал последние части кода следующим образом:

let line = NSString(data: buffer.subdataWithRange(NSMakeRange(0, range.location + 1)),
        encoding: encoding)
    buffer.replaceBytesInRange(NSMakeRange(0, range.location + range.length), withBytes: nil, length: 0)
    println("COMPLETE LINE IS \(line)")
    if line!.containsString("\n"){
        println("CONTAINS NEW LINE")
        //println("BUFFER IS \(buffer)")
        //
        println("COMPLETE LINE IS \(line)")
        return line
    }
    else {

        println("NO LINE!")
        atEof == true
        return nil
    }

Идея состоит в том, чтобы пройти через все строки, содержащие \n, и исключить одну строку, которая является последней, и не должна иметь \n. Но! Несмотря на то, что я проверил непечатаемые символы и не было \n, вот удивительный вывод консоли: Optional("lastline_blablabla\n") Вероятно, теперь вопрос в том, как остановиться на последней строке, даже если она содержит \n?

Если вам нужно получить данные из URL-адреса, мой код выше (тот, который находится под первым обновлением), будет работать

Но моя собственная проблема с \n имеет несколько способов решения. Один из них я использовал в своем коде. Поскольку это очень индивидуально, я не буду публиковать решение для \n в конце проблемы с файлом. Кроме того, я не уверен, что мои оба решения для urlStreamReader и \n являются лучшими, поэтому, если вы посоветуете какое-либо лучшее решение, это будет оценено мной и, возможно, некоторыми другими людьми.

Большое спасибо Мартину Р, который многое объяснил, написал отличный код и был очень приятным