créer un fichier avec NSData
prepa75
Membre
Bonsoir,
je suis désespérément en train d'essayer de reproduire une chose simple en C : créer,et remplir un document.txt
en C : il suffit de faire FILE* = fopen(fichier , "blabla.txt","w")
puis on enchaine avec des printf et scanf pour jouer avec le fichier...
je voudrai faire pareil en Obj-C (avant de poster j'ai fouiner partout,essayer de comprendre,suivi des tutos mais ça ne marche toujours pas)
voici mon code :
le résultat : j'ouvre mon fichier .txt (créer avec chemin_fichier) et il contient uniquement la phrase 1
Merci de m'indiquer si c'est la bonne classe,si j'ai pas fait d'erreur bête de débutant...
et quelle est la méthode qui correspond à un fprintf() ?
je suis désespérément en train d'essayer de reproduire une chose simple en C : créer,et remplir un document.txt
en C : il suffit de faire FILE* = fopen(fichier , "blabla.txt","w")
puis on enchaine avec des printf et scanf pour jouer avec le fichier...
je voudrai faire pareil en Obj-C (avant de poster j'ai fouiner partout,essayer de comprendre,suivi des tutos mais ça ne marche toujours pas)
voici mon code :
char phrase1[] = "ceci est la phrase 1";<br /> NSMutableData *data = [NSData dataWithBytes:phrase1 length:20];<br /> NSURL *url = [NSURL fileURLWithPath:chemin_fichier]; <br /> NSError *fileError = nil;<br /> [data writeToURL:url options:0 error:&fileError];<br /> <br /> char phrase2[] = "voila la phrase 2";<br /> <br /> NSData *data2 = [NSData dataWithBytes:phrase2 length:17];<br /> [data appendData:data2];<br /> <br /> }<br />
le résultat : j'ouvre mon fichier .txt (créer avec chemin_fichier) et il contient uniquement la phrase 1
Merci de m'indiquer si c'est la bonne classe,si j'ai pas fait d'erreur bête de débutant...
et quelle est la méthode qui correspond à un fprintf() ?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Tu voudrais qu'il fasse quoi de plus ?
Ah tu voudrais qu'il t'écrive la phrase2, donc data2, dans ton fichier ? Ah mais pour ça faut p'tet lui demander :P
Tu n'as fait writeToURL:options:error: qu'une seule fois, pour écrire le contenu du premier "data", normal donc qu'il ne t'air écrit que le premier data ;-)
Déplace ton writeToURL:options:error: à la fin de ton code, pour qu'il écrire le data après que tu as fait le "appendData" et donc seulement une fois que data contient à la fois phrase1 et phrase2.
Sinon les méthodes writeToFile: etc sont pratiques pour écrire directement un bloc de NSData dans un fichier. Mais si tu veux écrire séquentiellement, par petits bouts, dans un fichier, tu peux utiliser des API plus fines (un peu plus bas niveau disons) : cf le Programming Guide associé.
En particulier l'utilisation de NSFileHandle est bien plus proche de ce que tu ferais en C avec FILE*, fopen, fwrite (ou fprintf) et fclose, là où NSData et writeToURL: sont plus haut niveau (et plutôt orientées archivage/sérialisation).
je suis content de moi , même si j'ai passé 4H devant les différentes docs j'ai réussi a utiliser intelligemment celle d'Apple c'est ma tournée...
sinon j'ai essayer ce que tu m'as dit :
et j'ai droit à cette belle erreur (avec le fichier qui contient que la 1ere phrase...) :
C'est ce que tu fais tu vas me dire, puisque tu as déclaré data et data2 comme NSMutableData ?
Eh bien perdu, car même si elles sont déclarées comme ça, ce sont des NSData que tu mets dans ces variables, puisque tu appelles dataWithBytes:length: sur NSData et pas NSMutableData !
j'ai compris la subtilité Ali je dois donc utiliser erreur d'inatention :P
2eme question : j'essaye d'écrire dans un Filehandle mais c'est malheuresement sans succés...
voici mon code :
il y a une erreur pour (int)fileDescriptor j'ai mis 0 par pur hasard car je ne sais pas ce que l'on doit mettre, comment la description d'un fichier peut être un int ? je n'ai pas trouvé d'information sur ce fileDescriptor...
Creating a File Handle Object
NSFileHandle is a class clusters, file handle objects are not actual instances of the NSFileHandle class but of one of its private subclasses. Although a file handle object's class is private, its interface is public, as declared by the abstract superclass NSFileHandle.
Generally, you instantiate a file handle object by sending one of the fileHandle... messages to the NSFileHandle class object. These methods return a file handle object pointing to the appropriate file or communications channel. As a convenience, NSFileHandle provides class methods that create objects representing files and devices in the file system and that return objects representing the standard input, standard output, and standard error devices. You can also create file handle objects from file descriptors (such as found on BSD systems) using the initWithFileDescriptor: and initWithFileDescriptor:closeOnDealloc: methods. If you create file handle objects with these methods, you “own†the represented descriptor and are responsible for removing it from system tables, usually by sending the file handle object a closeFile message.
Le file descriptor est un numéro qui est renvoyé lorsqu'un ouvre un fichier. C'est utile si tu accèdes directement au système de fichier via POSIX.
À vrai dire, je n'ai jamais eu besoin d'utiliser NSFileHandle, NSFileManager répond à 90 % des besoins. Cependant, les méthodes +fileHandleForWritingAtPath: et cie te conviendront mieux.
En effet tu appelles [tt][filehandle initWithFileDescriptor:0][/tt] mais depuis quand on appelles "init" sans appeler "alloc" avant ? Tu appelles une méthode d'instance sur une instance... pas initialisée (et même pas mise à nil lorsque tu déclares ta variable, donc elle peut pointer n'importe où dans la mémoire et dans ce cas plantages assurés)...
Donc soit tu fais alloc/init, soit tu utilises un constructeur de commodité, mais pas init tout seul sans avoir fait le alloc ! Quant au File Descriptor, oui c'est un entier, ça vient de la base POSIX sur laquelle se base NSFileHandle comme indiqué par Céroce (plus d'infos sur wikipedia par exemple), mais dans ton cas tu n'as aucun besoin d'utiliser ça puisque tu ne souhaites pas initialiser ton NSFileHandle à partir d'un FileDescriptor qui t'aurait été retourné par un appel à une fonction système POSIX, donc c'est bien le constructeur de commodité que tu utilises en 2e ligne qu'il faut utiliser à la place.
Autrement, le système de fichiers possède des systèmes de caches, alors il n'est sûrement pas nécessaire d'écrire dans le fichier, mais le fermer, peut-être que oui.
Il n'a pas de raison de créer le fichier si tu ne lui as rien demandé d'écrire (même pas du vide), tu ne lui a pas demandé de créer de fichier, mais de créer un objet de type "FileHandle" (un "manipulateur de fichiers" si tu veux).
Tu peux créer une instance de NSFileHandle pour lire ou écrire un fichier, dans tous les cas instancier l'objet NSFileHandle ne crée en rien le fichier. Une fois que tu as le NSFileHandle, donc ce manipulateur de fichiers on va dire, tu peux appeler des méthodes dessus, soit pour créer le fichier correspondant, ou pour écrire sur le disque dans le fichier (ce qui va le créer s'il n'existe pas), etc.
PS : Et bonnes remarques de Céroce également sur les chemins et la fermeture du FileHandle
Voici mon code pour obtenir le chemin choisi par l'utilisateur :
il n'y a pas de souci il marche nikel lorsque j'utilise les NSMutableData donc si j'ai bien compris je doit utiliser un – writeData: pour créer le fichier automatiquement c'est ça ? ce qui va nous donner :
aurais-je oublier quelque chose ? la NSString chemin_fichier est par exemple : /Users/prepa75/Deskop/test.txt
Tant que tu ne fermes pas ton fichier (ou ne force pas la synchronisation) il ne fera pas l'écriture, car l'écriture est bufferisée pour éviter les accès continus au disque au risque de plomber les perfs.
pourtant c'est tout bon non ? je déclare, je ferme, je crée le *data et je l'écrit dans le dit fichier qui n'apparait pas sur le bureau GRRR >:(
et le closefile il faut le mettre à la fin non (ce qui est déja beaucoup plus logique :P )
Hélas le fichier n'apparait pas à l'emplacement choisi...
j'ai beau essayer tout les trucs qui trainent sur internet ça ne marche pas >:(
voici donc ce que j'ai fait (oui je sais c'est un peu triché mais la je suis vraiment bloqué :P )
et j'ai un beau fichier qui s'est crée sur mon bureau
En soi, ce n'est pas mal d'utiliser FILE* : après tout, Objective-C n'est qu'un sur-ensemble du C.
Par contre, il est dommage de se priver d'outils qui permettent de rendre les choses plus fiables.
chemin_char[300] : tu te prives des chemins de plus de 300 caractères
getCString : tu te prives des caractères UTF8
fopen() : en cas d'échec, le diagnostic est plus difficile à faire
printf(...) tu te prives des outils Cocoa pour former les chaà®nes de caractères.
Franchement, tu devrais profiter de n'avoir pas de grosses contraintes de développement pour te familiariser avec des morceaux de Cocoa que tu ne maà®trises pas. C'est l'occasion de s'enrichir !
j'y reviendrai dessus dans quelques mois lorsque j'aurai mieux compris certaines choses,pour le moment je suis sur la NSThread que j'avais mis de coté et maintenant avec un ptit tuto clair que j'ai trouvé je pense être capable de m'en sortir tout seul.ça fera surement pareil avec la NSFileHandle
Ze m'esplik :
Quand tu écris (en C)
Avec Cocoa tu écris
Sinon tu vas te retrouver à envoyer des messages à nil, ce qui n'est pas interdit mais ne fait rien du tout....
En fait je suis un peu perturbé par ton chemin_fichier qui sort d'une methode qui contient chooseDirectory, parce que si c'est un répertoire je ne suis pas certain que mettre un .txt au bout te donne un chemin valide.
Tu peux vérifier si ton fichier est là avec
voici le code que j'ai compilé :
comme tu l'as dit j'ai enlever l'ajout du .txt ce qui est bizarre c'est que le chemin est valide lorsque je le transphorme en char mais ne l'est pas lorsque je le laisse en une NSString
2eme chose bizarre quand je me battait pour faire apparaitre le fichier, *fileHandle n'était pas nil et pourtant le fichier n'aparaissait pas à son emplacement désiré...
en fait je met un chooseDirectory car une fenetre s'ouvre et l'utilisateur rentre le nom du fichier à créer ainsi que son emplacement.c'est bien la bonne méthode non ? il faut qu'il choisisse un dossier qui contiendra le fichier.
hth
c'est bizarre j'ai plus de temps libre en vacances qu'en prépa bref me revoici :P
Merci laudema pour ta réponse complète, j'ai bien analysé le code et j'ai compris le fonctionnement et le principe pour créer un fichier.
En fait c'est bon c'est devenu logique dans ma tête c'est bon signe
j'ai juste une question : dans ce code la :
le option:0 sert à quoi ? quels sont les autres valeurs qui peuvent être utilisées et en quelles circonstances ? parsque j'ai rien trouvé à ce sujet su la doc.
encore merci,j'ai tout compris
C'est pourtant bien indiqué.
je crois que je vais sérieusement me mettre à l'anglais informatique...ça sert...
J'imagine que ça a à voir avec l'écriture "atomique" ou pas du fichier mais je ne vois pas comment choisir. D'habitude on a juste une série de chaines qui correspondent aux valeurs numériques en regard et c'est plus lisible qu'un chiffre dont on oublie vite ce qu'il voulait dire.
Pour traduire l'anglais informatique, en plus du site http://forum.wordreference.com/ qui offre de bonnes traductions et des forums où elles sont débattues, tu as aussi l'option de chercher dans Wikipedia en anglais, souvent il y a un lien pour une page en français..
PS: sais pas si c''est chez moi seulement mais dans Safari cette page n'arrête pas de "flasher" en fait défile jusqu'en bas puis revient, c'est assez désagréable.