LES FICHIERS ET LES FONCTIONS ASSOCIÉES
1 GÉNÉRALITÉS
Un fichier est un ensemble de données plus ou moins structurées stocké sur un support permanent (il est toutefois possible de créer de fichiers en mémoire mais l'intérêt en PAWN reste limité).
Un fichier peut être vu comme une boite avec des cases où chaque case est numérotée (à partir de 0) et contient un octet.
De ce fait, les fonctions de gestion de fichier permettent d'ouvrir la boite, de se positionner sur une case donnée, de récupérer le contenu d'une ou plusieurs cases et de refermer la boite.
On considère généralement deux types de fichiers : les fichier textes (que l'on peut ouvrir directement avec notepad par exemple) et les fichiers binaires.
Mais les fichiers textes ne sont rien d'autres que des fichiers binaires ne contenant (presque) que des caractères lisibles.
Un fichier est identifié par son nom.
Exemples : VEHICULES.TXT, SPAWN.DAT, TEAMS.BANNIES.BIN, ...
Une fois ouvert, un fichier est identifié par une variable de type File.
Remarques :
- L'extension n'est pas obligatoire,
- Sous Windows, il n'y a pas de différence entre les miniscules et les majuscules (case insensitive). Les fichiers toto.txt, TOTO.txt ou ToTo.TXT ne seront qu'un seul et même fichier. Sous Linux, les fichiers cités précédemment seront trois fichiers distincts. Il est important d'avoir ceci à l'esprit car un script qui accède à des fichiers peut fonctionner parfaitement sous Windows et ne plus fonctionner du tout sur un serveur Linux.
Sous SAMP, les fichiers sont stockés dans le sous-répertoires scriptfiles (ou un des ses sous-répertoire) contenu dans le répertoire du serveur et il n'est possible de les stocker ailleurs.
Pour pouvoir utiliser les fonctions de gestions de fichiers, il faut inclure file.inc dans le script.
#include <file>
2 OUVERTURE D'UN FICHIER
Pour pouvoir utiliser les données contenues dans un fichier, il faut tout d'abord l'ouvrir.
L'ouverture d'un fichier se fait au moyen de la fonction fopen :
native File:fopen(const name[], filemode: mode = io_readwrite);
Le premier paramètre de cette fonction est le nom du fichier que l'on veut ouvrir.
Le deuxième paramètre indique comment va être ouvert le fichier.
Ce paramètre peut prendre une des valeurs suivante :
io_read -> Ouverture d'un fichier existant en lecture seule. Il ne sera pas possible d'écrire dans le fichier.
io_write -> Création d'un fichier qui n'existe pas pour écriture. Il ne sera pas possible de lire dans le fichier.
io_readwrite -> Ouverture d'un fichier existant en lecture/écriture ou création d'un nouveau fichier.
io_append -> Ouverture d'un fichier existant en écriture seule. Il ne sera pas possible de lire dans le fichier.
Remarque :
Dans la plupart des cas, on utilisera io_readwrite qui, de plus, est la valeur par défaut pour ce paramètre
La valeur de retour de fopen est de type File et sera ensuite utilisée pour accéder au fichier.
On appellera dorénavant cette valeur le handle du fichier.
Si l'ouverture échoue (fichier introuvable, caractère incorrect dans le nom du fichier, ...), la valeur de retour vaudra 0.
Exemple qui crée un fichier vide dans le répertoire scriptfile (ou ouvre le fichier si il existe déjà) :
new File:MonFichier;
MonFichier = fopen ("toto.txt", io_readwrite);
if (MonFichier != File:0) // On ne compare pas directement à 0 sinon ceci provoque un warning
{
/* On ferme le fichier */
fclose (Monfichier);
}
else
{
printf ("Erreur d'ouverture du fichier\n");
}
3 FERMETURE DU FICHIER
La fermeture du fichier a pour effet de libérer le fichier et d'écrire physiquement sur le disque les données qui se trouvent éventuellement dans le cache du disque.
La fermeture d'un fichier se fait au moyen de la fonction de la fonction fclose :
native bool:fclose(File: handle);
Le paramètre de cette fonction est un handle de fichier valide.
ATTENTION : Ne pas utiliser fclose avec handle invalide.
Cette fonction retourne true (1) lorsque la fermeture a été effectuée correctement et false (0) dans le cas contraire.
ATTENTION : Ne pas utiliser le code retour de cette fonction, ceci n'a pas été vérifié (cf wiki SAMP).
4 POSITIONNEMENT DANS LE FICHIER
Le positionnement dans un fichier est appelé index de lecture/écriture. Ceci correspond à la position de l'octet qui sera lu ou écrit.
Chaque lecture ou écriture incrémente l'index de lecture/écriture du nombre d'octet lu ou écrit.
Après ouverture, l'index de lecture/ecriture est positionné au début du fichier ou à la fin si le fichier est ouvert avec l'option io_append.
Il est possible de déplacer l'index sans faire de lecture ou d'écriture au moyen de la fonction fseek :
native fseek(File: handle, position = 0, seek_whence: whence = seek_start);
Le premier paramètre de cette fonction est le handle sur un fichier ouvert.
Le deuxième paramètre contient la position relative (donc positive ou négative) en fonction du troisième paramètre.
Le troisième paramètre contient la position de référence et peut prendre une des trois valeurs suivantes :
seek_start -> Début du fichier
seek_current -> Position courante
seek_end -> Fin du fichier
Exemples :
Sauter 5 octets dans le fichier :
fseek (Fic, 5, seek_current);
Revenir de 7 octets en arrière :
fseek (Fic, -7, seek_current);
Aller au 18ème octet du fichier
fseek (Fic, 18, seek_start);
Aller à l'avant-dernier octet du fichier :
fseek (Fic, -1, seek_end);
Aller au début du fichier :
fseek (Fic);
ou
fseek (Fic, 0, seek_start);
Le valeur de retour de fseek donne le déplacement effectué dans le fichier en octet.
Par exemple, si l'index de lecture est positionné au début du fichier alors
fseek (Fic, 18, seek_start);
renverra 18 et
fseek (Fic, 0, seek_end); //Dernier octet du fichier
renverra la taille du fichier.
5 LECTURE DANS UN FICHIER
Une fois le fichier ouvert par la fonction fopen, il est possible de lire les données qu'il contient.
Il existe trois type de lecture dans SAMP : la lecture de chaînes de caractères, la lecture de données brutes et la lecture d'un caractère.
5.1 LECTURE DE CHAINES
Pour lire une chaîne de caractères, on utilise la fonction fread :
native fread(File: handle, string[], size = sizeof string, bool: pack = false);
Le premier paramètre de cette fonction est le handle sur un fichier ouvert en lecture ou en lecture/écriture.
Le deuxième paramètre est une variable de type tableau qui recevra les données lues.
Le troisième paramètre correspond à la taille maximale que peut contenir le tableau passé en deuxième paramètre.
Le quatrième paramètre indique que les données lues seront compactées (les données compactées ne sont pas l'objet de ce tutoriel, il est préférable de laisser ce paramètre à false)
La valeur de retour de fread correspond au nombre d'octets effectivement lus dans le fichier. Si la valeur de retour est 0, aucune lecture n'a été faîte.
ATTENTION : Ce nombre ne correspond jamais à la taille de la chaîne. Il est donc peu recommandé de s'en servir pour connaître la taille de la chaîne lue.
5.2 LECTURE DE DONNÉES BRUTES
Il est possible de lire des données binaire (brutes) dans un fichier au moyen de la fonction fblockread :
native fblockread(File: handle, buffer[], size = sizeof buffer);
Le premier paramètre de cette fonction est le handle sur un fichier ouvert en lecture ou en lecture/écriture.
Le deuxième paramètre est une variable de type tableau qui recevra les données lues.
Le troisième paramètre correspond au nombre d'éléments du tableau qu'on veut lire.
La valeur de retour de la fonction donne le nombre d'éléments lus.
Remarque :
Ici, on parle bien d'éléments d'un tableau et non pas d'octets. En Pawn, sous SAMP, un élément fait 4 octets.
Exemple :
new File:Fic;
new Tableau[5];
Fic = fopen ("TOTO.BIN", io_readwrite);
if (Fic != File:0)
{
/* Lecture de 3 éléments */
fblockread (Fic, Tableau, 3));
fclose (Fic);
}
else
{
printf ("Erreur d'ouverture du fichier TOTO.TXT\n");
}
5.3 AUTRE FONCTION DE LECTURE
Il est aussi possible de ne lire qu'un seul caractère dans un fichier ouvert au moyen de la fonction fgetchar :
native fgetchar(File: handle, value, bool: utf8 = true);
Le premier paramètre de cette fonction est le handle sur un fichier ouvert en lecture ou en lecture/écriture.
Le deuxième paramètre est une variable qui recevra la valeur du caractère lu.
Le troisième paramètre indique si l'on est en ANSI (1 octet par caractère) ou en UTF8 (2 octets par caractère).
Remarque :
Pour les langues comme le français ou l'anglais, il est préférable de mettre ce paramètre à false.
La valeur de retour de fgetchar n'est pas documentée et ne semble correspondre à rien, il est plus prudent de ne pas s'en servir.
6 ÉCRITURE DANS UN FICHIER
L'écriture dans un fichier suis les mêmes principes que la lecture.
6.1 ÉCRITURE DE CHAINES
Pour écrire une chaîne de caractères, on utilise la fonction fwrite :
native fwrite(File: handle, const string[]);
Le premier paramètre de cette fonction est le handle sur un fichier ouvert en écriture ou en lecture/écriture.
Le deuxième paramètre est une variable de type tableau qui contient la chaîne à écrire.
La valeur de retour de fwrite correspond au nombre d'octets effectivement écrits dans le fichier. Si la valeur de retour est 0, aucune ecriture n'a été faîte.
ATTENTION : Ce nombre ne correspond jamais à la taille de la chaîne à écrire.
6.2 ÉCRITURE DE DONNÉES BRUTES
Il est possible d'écrire des données binaire (brutes) dans un fichier au moyen de la fonction fblockwrite :
native fblockwrite(File: handle, const buffer[], size = sizeof buffer);
Le premier paramètre de cette fonction est le handle sur un fichier ouvert en écriture ou en lecture/écriture.
Le deuxième paramètre est une variable de type tableau qui contient les données à écrire.
Le troisième paramètre correspond au nombre d'éléments du tableau qu'on veut écrire dans le fichier.
La valeur de retour de la fonction donne le nombre d'éléments écrits.
Remarque : Ici, on parle bien d'éléments d'un tableau et non pas d'octets. En Pawn, sous SAMP, un élément fait 4 octets.
Exemple :
new File:Fic;
new Tableau[5] = {1, 2, 3, 4, 5};
Fic = fopen ("TOTO.BIN", io_readwrite);
if (Fic != File:0)
{
fblockwrite (Fic, Tableau));
fclose (Fic);
}
else
{
printf ("Erreur d'ouverture du fichier TOTO.BIN\n");
}
Voici, en binaire, le contenu du fichier TOTO.BIN après exécution de l'exemple ci-dessus :
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00
6.3 AUTRE FONCTION D'ÉCRITURE
Il est aussi possible de n'écrire qu'un seul caractère dans un fichier ouvert au moyen de la fonction fputchar :
native bool:fputchar(File: handle, value, bool: utf8 = true);
Le premier paramètre de cette fonction est le handle sur un fichier ouvert en écriture ou en lecture/écriture.
Le deuxième paramètre est une variable qui contient la valeur du caractère à écrire.
Le troisième paramètre indique si l'on est en ANSI (1 octet par caractère) ou en UTF8 (2 octets par caractère).
Remarque :
Pour les langues comme le français ou l'anglais, il est préférable de mettre ce paramètre à false.
La valeur de retour de fputchar vaut true si l'écriture est correcte, false sinon.
7 AUTRES FONCTIONS SUR LES FICHIERS
7.1 SUPPRESSION D'UN FICHIER
Il est possible de supprimer un fichier au moyen de la fonction fremove :
native bool:fremove(const name[]);
Le premier paramètre de cette fonction est le nom du fichier que l'on veut supprimer.
La valeur de retour de fremove vaut true si le fichier a été supprimé correctement, false sinon.
7.2 TAILLE D'UN FICHIER
Il est possible de récupérer la taille d'un fichier ouvert grâce à la fonction flength :
native flength(File: handle);
Le premier paramètre de cette fonction est le handle sur un fichier ouvert.
La valeur de retour est la taille en octet du fichier.
++
Syg