Les bases pour accéder à un fichier
Tout le monde connait les fonctions fopen(), fread(), ...
Eh bien oubliez les dans le monde de Microsoft.
Vous allez me dire que pour la portabilité, ce n'est pas top ! Je suis d'accord, mais de toute façon, que ce soit vers un système ou un autre, la portabilité d'un programme n'a jamais été chose facile. C'est de bonne guerre, chacun faisant en sorte de fidéliser d'une manière ou d'une autre ses clients...
Les fonctions Microsoft restent similaires à toutes celles que vous avez déjà pu voir (MS-DOS, Unix, Atari ST). Si vous connaissez déjà, ce ne sera pas bien difficile...
Voici donc les fonctions pour gérer les fichiers sous Windows:
Ouvrir un fichier
Il existe une fonction pour ouvrir un fichier, il s'agit de la fonction OpenFile(). Mais je devrais dire "il s'agissait". Si cette fonction est toujours disponible, ce n'est que pour rester compatible avec les versions 16 bits. Préférez plutôt la commande suivante...
Créer/Ouvrir un fichier
La fonction pour créer ou ouvrir un fichier est CreateFile(). Nous sommes en multi-tâches, donc cette fonction va vous permettre de paramètrer le type de partage du fichier avec d'autres applications.
HANDLE CreateFile(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
Les paramètres étant:
lpFileName pour le nom du fichier.
DwDesiredAccess pour le type d'accès que l'on désire faire (Dans
le cas ou le fichier serait déjà vérouillé par une
autre application, le système va alors vérifier que l'autre applicaion
autorise ce type d'accès). Les valeurs seront pour:
En lecture:GENERIC_READ,
E n écriture:GENERIC_WRITE,
L es deux:GENERIC_READ | GENERIC_WRITE,
ou NULL pour vérifier l'existance d'un fichier par exemple.
dwShareMode pour indiquer le type d'accès que vous allez autoriser pour les autres applications (Dans le cas où une autre application essayerait d'accèder au fichier pendant que vous travaillez dessus):
Non partagé se sera NULL,
partagé en lecture:FILE_SHARE_READ,
partagé en écriture:FILE_SHARE_WRITE
ou encore les deux: FILE_SHARE_READ | FILE_SHARE_WRITE
lpSecurityAttributes pour indiquer qu'un processus fils peut ou non hériter
du fichier. NULL n'autorisant pas l'héritage.
dwCreationDisposition pour indiquer la méthode à utiliser pour
lire ou créer le fichier:
CREATE_NEW: Création du fichier. Si le fichier existe déjà, la fonction retournera une erreur.
CREATE_ALWAYS: Création d'un fichier ou écrasement du fichier si celui-ci existe déjà.
OPEN_EXISTING: Ouverture d'un fichier existant. Si le fichier n'existe pas, le fonction retourne une erreur.
OPEN_ALWAYS Ouverture du fichier. Si le fichier n'existe pas il est créé.
dwFlagsAndAttributes indique les attributs utilisés pour créer
le fichier. Si le fichier existe déjà, les nouveaux attributs
seront combinés aux anciens.
Attributs | Désignations |
FILE_ATTRIBUTE_ARCHIVE | Ce fichier peut-être archivé |
FILE_ATTRIBUTE_ENCRYPTED |
Le fichier ou le répertoire est crypté. Sans effet si l'attribut FILE_ATTRIBUTE_SYSTEM est positionné Si l'attribut est posé sur un répertoire, alors l'attribut est deviendra un atribut par défaut pour tous les nouveaux fichiers ou répertoires. |
FILE_ATTRIBUTE_HIDDEN | Le fichier est caché. |
FILE_ATTRIBUTE_NORMAL | Fichier normal, il n'est évidemment pas pris en compte si d'autres attributs sont posés ! |
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | Le fichier ne peut pas être indexé |
FILE_ATTRIBUTE_READONLY | Fichier en lecture seul ! |
FILE_ATTRIBUTE_SYSTEM | Fichier système ! |
FILE_ATTRIBUTE_TEMPORARY | Fichier temporaire. |
Il exite d'autres attibuts, mais non utiles pour le moment.
En sortie, la fonction retourne un handle sur le fichier ouvert ou INVALID_HANDLE_VALUE en cas d'erreur.
Remarque:Si vous essayez d'accèder à un fichier sur une disquette
ou un CD alors qu'il n'y a pas de disquette ou de CD dans le lecteur, le système
va
afficher un message vous demandant d'insérer le média correspondant.
Pour éviter cela, utiliser la fonction SetErrorMode(SEM_FAILCRITICALERRORS).
Lire le contenu d'un fichier
La commande permettant de lire le contenu d'un fichier est ReadFile()
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
);
Les paramètres étant:
hFile pour le handle du fichier retourné par la fonction CreateFile().
lpBuffer qui va être un pointeur sur un buffer qui va recevoir les données.
nNumberOfBytesToRead qui sera le nombre d'octet à lire.
lpNumberOfBytesRead pointeur sur une variable qui recevra le nombre d'octets
lus (Cette variable devra être DWORD). Si la valeur est différente
à celle demandée c'est que la fin du fichier est atteinte.
lpOverlapped sera positionné à NULL dans un premier temps.
Remarque:Si vous essayez de lire un fichier sur une disquette ou un CD alors
qu'il n'y a pas de disquette ou de CD dans le lecteur, le système va
afficher un message vous demandant d'insérer le média correspondant.
Pour éviter cela, utiliser la fonction SetErrorMode( SEM_NOOPENFILEERRORBOX).
Si lpOverlapped
est NULL, lpNumberOfBytesRead ne devra pas être NULL. De
même Si lpNumberOfBytesRead est NULL, lpOverlapped ne devra
pas être NULL.
Ecrire dans un fichier
La fonction est similaire à ReadFile(), sauf qu'elle se nomme WriteFile() !!!
BOOL WriteFile(
HANDLE hFile,
LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped
);
Pour tout le reste, c'est 100% pareil !
Fermer le fichier
BOOL CloseHandle(
HANDLE hObject
);
Se positionner dans le fichier
Pour se positionner dans le fichier à partir du début, de la position courante ou de la fin du fichier:
DWORD SetFilePointer(
HANDLE hFile,
LONG lDistanceToMove,
PLONG lpDistanceToMoveHigh,
DWORD dwMoveMethod
);
Les paramètres étant:
hFile pour le handle du fichier.
lDistanceToMove: partie basse d'un nombre sur 64 bits du déplacement
si lpDistanceToMoveHigh n'est pas NULL. Sinon, c'est un nombre signé
sur 32 bits.
lpDistanceToMoveHigh: pointeur sur une variable contenant la partie haute d'un
nombre sur 64 bits signé correspondant au déplacement. si la valeur
passée est NULL, le déplacement sera sur 32 bits.
dwMoveMethod: Origine du déplacement (voir le tableau ci-dessous)
Attributs | Description |
FILE_BEGIN | Déplacement à partir du début du fichier |
FILE_CURRENT | Déplacement à partir de la position actuelle ou courante du fichier |
FILE_END | Déplacement à partir de la fin du fichier |
En sortie: Si la valeur de lpDistanceToMoveHigh est NULL, la fonction retourne INVALID_SET_FILE_POINTER si problème, sinon se sera la nouvelle position du pointeur.
Si la valeur de lpDistanceToMoveHigh n'est pas NULL, la fonction retourne INVALID_SET_FILE_POINTER si problème, sinon se sera la partie basse de la nouvelle position du pointeur. La variable indiquée dans lpDistanceToMoveHigh recevra la partie haute de la nouvelle position.
Problème:
Il faudra vérifier que l'on ne confond pas INVALID_SET_FILE_POINTER avec un déplacement. Pour cela, il faut impérativement utiliser GetLastError(). Si la valeur retournée est NO_ERROR, c'est que tout est ok.
Pour se positionner à la fin d'un fichier:
BOOL SetEndOfFile(
HANDLE hFile
);
Connaîte la taille d'un fichier:
Pour connaître la taille d'un fichier, le plus simple sera d'utiliser la fonction GetFileSize()
DWORD GetFileSize(
HANDLE hFile,
LPDWORD lpFileSizeHigh
);
lpFileSizeHigh pourra être NULL si on ne veut pas avoir la partie haute
de la taille.
Là aussi, on peut avoir des problèmes:
Il faudra vérifier que l'on ne confond pas INVALID_SET_FILE_POINTER avec un déplacement. Pour cela, il faut impérativement utiliser GetLastError(). Si la valeur retournée est NO_ERROR, c'est que tout est ok.
Remarque: Cette fonction retourne une taille en DWORD. Il faudra utiliser GetFileSizeEx() pour connaître des tailles plus importantes.