Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
3044 connectés 

  FORUM HardWare.fr
  Programmation
  C

  Créer un fichier vide en C. [Résolu]

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Créer un fichier vide en C. [Résolu]

n°1261266
meumeul
Stay Heavy
Posté le 07-12-2005 à 21:03:46  profilanswer
 

Bonjour,
Je souhaite allouer une certaine place a un fichier, et le remplir par la suite.
Mettons que je veux faire un fichier vide de 200 octets , je fais
 

Code :
  1. int fd;
  2. if((fd = open("data2",O_CREAT)) == -1)
  3.       erreur("open for allocating\n" );
  4. lseek(fd,199,SEEK_SET);
  5. write(fd,"0",1);
  6. close(fd);


 
ca me cree bien un fichier data2 mais de 0 octets :S j'avais d'abord essayer un lseek de 200 sans rien écrire,  
mais cela ne marchait pas non plus ...
 
je sais que c'est une question trés bête, ne me linchez pas please :)
merci

Message cité 1 fois
Message édité par meumeul le 08-12-2005 à 17:09:37
mood
Publicité
Posté le 07-12-2005 à 21:03:46  profilanswer
 

n°1261286
manatane
En vous remerciant, bonsoir
Posté le 07-12-2005 à 22:00:56  profilanswer
 

Tu peux utiliser truncate ou ftruncate, le prototype doit etre du truncate( nom_du_fichier, longueur ),  si la taille du fichier ou du descripteur spécifié est inférieure à longueur le fichier est étendu et la différence entre l'ancienne EOF et la nouvelle est matérialisée par un trou (ie des 0 qui ne sont pas alloues physiquement sur le disque)

n°1261287
Emmanuel D​elahaye
C is a sharp tool
Posté le 07-12-2005 à 22:05:54  profilanswer
 

meumeul a écrit :

Je souhaite allouer une certaine place a un fichier, et le remplir par la suite.
Mettons que je veux faire un fichier vide de 200 octets , je fais


  • Un fichier vide est un fichier de 0 octets.
  • Un fichier avec 200 octets dedans (à quelle valeur ?) n'est évidemment pas vide.


Je pense qu'il y a un problème de conception quelque part. Que veux tu faire exactement ?
 
Sinon, pour créer un fichier de 200 octets (à 0, par exemple) :  


#include <stdio.h>
 
int main (void)
{
   FILE *fp = fopen ("data.txt", "w" );
 
   if (fp != NULL)
   {
      char a[200] = {0};
 
      fwrite (a, sizeof a, 1, fp);
      fclose (fp), fp = NULL;
   }
   return 0;
}



 Le volume dans le lecteur C s'appelle 427409
 Le numéro de série du volume est 8873-ADFB
 
 Répertoire de C:\dev\forums\OP
 
07/12/2005  22:05               200 data.txt
               1 fichier(s)              200 octets
               0 Rép(s)  155 849 830 400 octets libres


Message édité par Emmanuel Delahaye le 07-12-2005 à 22:06:47

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1261310
matafan
Posté le 07-12-2005 à 22:28:35  profilanswer
 

meumeul, ton code est bon a deux choses pres :
 
1) C'est O_CREAT | O_WRONLY, qu'il faut utiliser, pas seulement O_CREAT
 
2) write prend en argument l'adresse du buffer que tu veux ecrire, pas directement les donnees que tu veux ecrire. Donc c'est write(fd, &c, 1) avec char c = 0, pas write(fd,"0",1).
 
Mais attention, le resultat n'est pas forcement ce a quoi tu t'attend. Suivant l'OS et suivant l'offset du lseek (i.e. avec un grand offset), tu peux te retrouver avec un "sparse file". Ca ne fait aucune difference en pratique (quand tu le lit, tu vois ce que tu as ecrit, et des 0 ou tu n'as pas ecrit), mais tout le fichier ne correspond pas forcement a des donnees sur le disque. Autrement dit ls -l te donnera la bonne taille (celle du lseek + 1), mais le fichier occupe moins de place que ca sur le disque.
 
Demonstration :

Code :
  1. #include <fcntl.h>
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. int
  5. main()
  6. {
  7.         int fd;
  8.         char c = 'a';
  9.         fd = open("sparse_file", O_CREAT | O_WRONLY);
  10.         if (fd == -1) {
  11.                 perror("open" );
  12.                 return 1;
  13.         }
  14.         if (sizeof c != write(fd, &c, sizeof c)) {
  15.                 perror("write 1" );
  16.                 return 1;
  17.         }
  18.         if (-1 == lseek(fd, 100000000, SEEK_SET)) {
  19.                 perror("lseek" );
  20.                 return 1;
  21.         }
  22.         if (sizeof c != write(fd, &c, sizeof c)) {
  23.                 perror("write 2" );
  24.                 return 1;
  25.         }
  26.         return 0;
  27. }


# ls -l sparse_file  
-rwsr-x---   1 root     system    100000001 Dec  7 14:59 sparse_file
# du -k sparse_file  
8       sparse_file


Dans l'exemple ci-dessus on voit que le fichier fait bien 100Mo, mais seulement deux blocs sont alloues sur le disque (8Ko, un bloc etant 4Ko sur ma machine). Par contre si je le lis, je vois bien mon 'a', un autre 'a' 100Mo plus loin, et des 0 entre.

Message cité 2 fois
Message édité par matafan le 07-12-2005 à 22:42:09
n°1261342
Sve@r
Posté le 07-12-2005 à 23:02:51  profilanswer
 

matafan a écrit :

meumeul, ton code est bon a deux choses pres :
 
1) C'est O_CREAT | O_WRONLY, qu'il faut utiliser, pas seulement O_CREAT
 
2) write prend en argument l'adresse du buffer que tu veux ecrire, pas directement les donnees que tu veux ecrire. Donc c'est write(fd, &c, 1) avec char c = 0, pas write(fd,"0",1).
 
Mais attention, le resultat n'est pas forcement ce a quoi tu t'attend. Suivant l'OS et suivant l'offset du lseek (i.e. avec un grand offset), tu peux te retrouver avec un "sparse file". Ca ne fait aucune difference en pratique (quand tu le lit, tu vois ce que tu as ecrit, et des 0 ou tu n'as pas ecrit), mais tout le fichier ne correspond pas forcement a des donnees sur le disque. Autrement dit ls -l te donnera la bonne taille (celle du lseek + 1), mais le fichier occupe moins de place que ca sur le disque.
 
Demonstration :

Code :
  1. #include <fcntl.h>
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. int
  5. main()
  6. {
  7.         int fd;
  8.         char c = 'a';
  9.         fd = open("sparse_file", O_CREAT | O_WRONLY);
  10.         if (fd == -1) {
  11.                 perror("open" );
  12.                 return 1;
  13.         }
  14.         if (sizeof c != write(fd, &c, sizeof c)) {
  15.                 perror("write 1" );
  16.                 return 1;
  17.         }
  18.         if (-1 == lseek(fd, 100000000, SEEK_SET)) {
  19.                 perror("lseek" );
  20.                 return 1;
  21.         }
  22.         if (sizeof c != write(fd, &c, sizeof c)) {
  23.                 perror("write 2" );
  24.                 return 1;
  25.         }
  26.         return 0;
  27. }


# ls -l sparse_file  
-rwsr-x---   1 root     system    100000001 Dec  7 14:59 sparse_file
# du -k sparse_file  
8       sparse_file


Dans l'exemple ci-dessus on voit que le fichier fait bien 100Mo, mais seulement deux blocs sont alloues sur le disque (8Ko, un bloc etant 4Ko sur ma machine). Par contre si je le lis, je vois bien mon 'a', un autre 'a' 100Mo plus loin, et des 0 entre.


 
Hum... avoir un chmod aléatoire sur un fichier lors de sa création n'est pas franchement une bonne idée (surtout que dans ton cas ça a donné un setuid sur un fichier appartenant à "root" !!!)
=> fd = open("sparse_file", O_CREAT | O_WRONLY, 0644);
 
Ou bien, pour vraiment être rigoureux
=> fd = open("sparse_file", O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
 

Message cité 1 fois
Message édité par Sve@r le 08-12-2005 à 12:12:45
n°1261367
matafan
Posté le 08-12-2005 à 00:06:11  profilanswer
 

Exact, oublie de ma part. En fait au debut j'avais pas de O_CREAT dans mon code, donc pas besoin de mode... Puis j'ai ajoute O_CREAT en oubliant d'ajouter le mode.

n°1261600
Sve@r
Posté le 08-12-2005 à 12:08:13  profilanswer
 

matafan a écrit :


Code :
  1. if (sizeof c != write(fd, &c, sizeof c)) {
  2. ...
  3. }




 
Ne vaut-il pas mieux comparer "if (write(...) < 0)" ???


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°1261848
meumeul
Stay Heavy
Posté le 08-12-2005 à 15:49:14  profilanswer
 

Sve@r a écrit :

Hum... avoir un chmod aléatoire sur un fichier lors de sa création n'est pas franchement une bonne idée (surtout que dans ton cas ça a donné un setuid sur un fichier appartenant à "root" !!!)
=> fd = open("sparse_file", O_CREAT | O_WRONLY, 0644);
 
Ou bien, pour vraiment être rigoureux
=> fd = open("sparse_file", O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);


 
trés rigoureuse remarque, je n'avais aucun droit sur ce fichier, et je ne captais pas pourquoi ...
merci, ca marche nickel. je vais essayer de le réouvrir et d'ecrire des blocs un peu partout dedans  
maintenant...

n°1261931
meumeul
Stay Heavy
Posté le 08-12-2005 à 17:09:22  profilanswer
 

Ok j'ai reussi à faire tout ce que je voulais, merci pour votre aide, tout n'était qu'en gros, une histoire de droits ... Merci pour les precision quand aux tailles des fichiers.
 
++


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  Créer un fichier vide en C. [Résolu]

 

Sujets relatifs
Pb Socket et fichierPython/unicode: écrire de gauche à droite/de droite à gauche [résolu]
Gestion des données d'un fichier TXTCréer et enregister une image avec wxwidgets
(résolu) surcharge operateur <<creer raccourci vers le bureau windows
Question sur commondialog [ résolu ]supprimer un fichier sous unix
[Resolu]basename sous vbe[C] Problemes rand() [résolu]
Plus de sujets relatifs à : Créer un fichier vide en C. [Résolu]


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR