Почему FileHandle непоследовательно возвращает 'nil' - PullRequest
0 голосов
/ 31 мая 2018

У меня есть приложение, которое непоследовательно возвращает 'nil' при использовании FileHandle для открытия файла для чтения.Я на OSX (10.13.4), XCode 9.4, Swift 4.1

Это приложение OSX использует NSOpenPanel (), чтобы получить список файлов, выбранных пользователем.Мой код класса 'model' открывает эти файлы для создания коллекции структур данных. Код, который делает это, начинается следующим образом и успешно получает FileHandle КАЖДЫЙ РАЗ для любого файла и может читать данные из файла.

private func getFITHeader(filename: String) {
    let file: FileHandle? = FileHandle(forReadingAtPath: filename)
    if file == nil {
        print("FITFile >>> File open failed for file \(filename)")
    }
    else {
        var databuffer: Data
        databuffer = (file?.readData(ofLength: 80))!
        :
        :
    }

Файлы также содержат блок двоичных данных, которые я обрабатываю в другой части приложения.Пока я разрабатываю код для этого, я временно жестко кодирую одно и то же имя файла, которое работает выше для целей тестирования.НО этот код (ниже) ВСЕГДА выдает исключение ' Поток 1: неустранимая ошибка: неожиданно обнаружил nil при развертывании необязательного значения ', когда он попадает в fileHandle? .Seek () - по какой-то причине попытка создатьFileHandle всегда возвращает nil, несмотря на то, что код функционально идентичен приведенному выше.

@IBAction func btnProcFile(_ sender: Any) {

    var data: Data
    let filename = "/Users/johncneal/Dropbox/JN Astronomy/Astronomy/Spectroscopy/RSpec_Analyses/Gamma_Cas/20161203/Gamma Cas_065.fit"

    let fileHandle: FileHandle? = FileHandle(forReadingAtPath: filename)
    fileHandle?.seek(toFileOffset: 2880) //skip past the headers

    let dataLenToRead = 1391 * 1039 * 2
    data = (fileHandle?.readData(ofLength: dataLenToRead))!
    :
    :
}

Код во второй функции прекрасно работает на игровой площадке (не придавая этому особого значения) и, что странноТакже работал, когда временно добавлен в другой проект.Вероятно, также стоит упомянуть, что длина пути к файлу, кажется, не имеет значения - он ведет себя одинаково на коротких путях.

Итак, вопрос в том, почему такое поведение FileHandle надежно несовместимо?

print () - имена файлов, представленные FileHandle (), показали, что они идентичны в каждом случае (см. Ниже).Так что я озадачен и расстроен этим - любые перспективы или обходные пути будут оценены.

/ Users / johncneal / Dropbox / JN Astronomy / Астрономия / Спектроскопия / RSpec_Analyses / Gamma_Cas / 20161203 / Gamma Cas_065.fit

/ Пользователи / johncneal / Dropbox / JN Astronomy / Астрономия / Спектроскопия / RSpec_Analyses / Gamma_Cas / 20161203 / Gamma Cas_065.fit

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

Нашел ответ - Песочница !!

Даррен - по совпадению я просмотрел маршрут на основе URL-адреса и обнаружил, что он «выбрасывает», в отчетах выдает правильные сообщения об ошибках.Низко и вот, они сообщили, что у меня не было разрешений на файл (что поначалу меня удивило, так как я, очевидно, являюсь администратором на моем Mac, и все файлы локальны и под моим именем пользователя.

Я немного больше исследований обратилсяк этой статье - https://forums.developer.apple.com/thread/96062, которая быстро выявила проблему с песочницей :-) Похоже, в последних версиях XCode он включен в «Правах».В посте также указывается, что диалоговое окно NSOpenPanel FileOpen возвращает «URL-адреса безопасности».Сначала я подумал, что это объясняет, почему код в первой функции работал, но я не совсем уверен, потому что я только передавал свойство url.path в FileHandle.

Однако отключение Sandbox в Entitlements заставляет все работатьпросто хорошо.Да, я знаю, что это не правильно делать в долгосрочной перспективе (или если я хочу, чтобы это пошло в App Store), поэтому я проверю правильный способ сделать это.По крайней мере, я могу теперь - спасибо за вклад.

0 голосов
/ 01 июня 2018

Инициализаторы FileHandle имеют неправильные имена.

Вы должны использовать FileHandle(forReadingFrom:URL) вместо FileHandle(forReadingAtPath:String).Первый - более новый API, который выдает ошибку, а не возвращает nil.Вы можете использовать сгенерированную ошибку, чтобы увидеть, почему она терпит неудачу, и ваши переменные гарантированно не равны нулю.

Например:

@IBAction func btnProcFile(_ sender: Any) {

    do {
        let fileUrl = URL(fileURLWithPath:"/Users/johncneal/Dropbox/JN Astronomy/Astronomy/Spectroscopy/RSpec_Analyses/Gamma_Cas/20161203/Gamma Cas_065.fit")

        let fileHandle = try FileHandle(forReadingFrom: fileUrl)
        fileHandle.seek(toFileOffset: 2880) //skip past the headers

        let dataLenToRead = 1391 * 1039 * 2
        let data: Data = fileHandle.readData(ofLength: dataLenToRead)
        // etc...
    } catch let error as NSError {
        print("FITFile >>> File open failed: \(error)")
        NSApp.presentError(error)
    }

}
...