2017-08-14 6 views
0

Je voudrais ouvrir un fichier de sortie nommé de manière unique pour écrire plist ou data, mais sans avoir de chance d'obtenir un handle en utilisant l'une ou l'autre routine URL de init (fileURLWithPath :) ou init (string :)FileHandle n'accepte pas mes URL pour l'accès en écriture

func NewFileHandleForWritingFile(path: String, name: String, type: String, outFile: inout String?) -> FileHandle? { 
    let fm = FileManager.default 
    var file: String? = nil 
    var uniqueNum = 0 

    while true { 
     let tag = (uniqueNum > 0 ? String(format: "-%d", uniqueNum) : "") 
     let unique = String(format: "%@%@.%@", name, tag, type) 
     file = String(format: "%@/%@", path, unique) 
     if false == fm.fileExists(atPath: file!) { break } 

     // Try another tag. 
     uniqueNum += 1; 
    } 

    outFile = file! 

    do { 
     let fileURL = URL.init(fileURLWithPath: file!) 
     let fileHandle = try FileHandle.init(forWritingTo: fileURL) 
     print("\(file!) was opened for writing") 
     //set the file extension hidden attribute to YES 
     try fm.setAttributes([FileAttributeKey.extensionHidden: true], ofItemAtPath: file!) 
     return fileHandle 
    } catch let error { 
     NSApp.presentError(error) 
     return nil; 
    } 
} 

débogueur montre

debugger shows

qui, pour cette URL de routine d'initialisation ajoute le schéma (file: //) mais sinon le même que l'autre, et je voudrais de préférer les méthodes plus récentes qui jettent reutrning (-1) quand ju st en utilisant des chemins. L'erreur lancée (2) est un ENOENT (pas une telle entité !?) que j'ai besoin d'un handle pour écrire à Je suis confus comment d'obtenir un autre? L'exemple de chemin est un nouveau dossier créé sur le bureau pour triage.

Répondre

2

Vous ne pouvez pas créer un descripteur de fichier dans un fichier inexistant. C'est ce qui provoque l'erreur ENOENT.

Utilisez FileManager createFile(atPath:contents:attributes:) pour créer le fichier juste avant de créer l'identificateur de fichier.

do { 
    fm.createFile(atPath: file!, contents: nil, attributes: [FileAttributeKey.extensionHidden: true]) 
    let fileURL = URL(fileURLWithPath: file!) 
    let fileHandle = try FileHandle(forWritingTo: fileURL) 
    print("\(file!) was opened for writing") 

    return fileHandle 
} catch let error { 
    NSApp.presentError(error) 
    return nil; 
} 
2

Contrairement à la réponse précédente, je recommande d'utiliser l'API de données write(to:options:) au lieu de createFile(atPath:contents:attributes:) de FileManager, parce qu'il est une API basée sur l'URL, ce qui est généralement être préférée à celles basées sur le chemin. La méthode Data renvoie également une erreur au lieu de renvoyer false si elle échoue. Par conséquent, si quelque chose ne va pas, vous pouvez indiquer à l'utilisateur pourquoi.

try Data().write(to: fileURL, options: [])

Je suggère également de remplacer la voie basée sur FileManager.fileExists(atPath:) avec l'URL basée checkResourceIsReachable():

if false == ((try? fileURL.checkResourceIsReachable()) ?? false)

+0

Eh bien, je suis encore sur la clôture par rapport aux données d'écriture ou un plist, mais Je vais garder cela à l'esprit, merci! – slashlos

+0

J'ai fini par créer une fonction variant qui renvoie une URL pour l'écriture afin que je puisse utiliser la méthode d'écriture de données suggérée: 'try data.write (to: fileURL)' – slashlos